diff --git a/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0001.patch b/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0001.patch new file mode 100644 index 0000000000..008f588bff --- /dev/null +++ b/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0001.patch @@ -0,0 +1,4863 @@ +From 8b47f269b83b172b22606806fe5ec272d974e797 Mon Sep 17 00:00:00 2001 +From: Michael Vrhel +Date: Mon, 22 Nov 2021 12:13:10 -0800 +Subject: [PATCH 6/7] Removal of globals in opvp device + +Thanks to Robin for suggesting the structure form +to get the globals at a common offset for the +raster and vector forms of the device. That coupled +with pushing the device through all the methods and +doing initialization was the biggest effort. + +Thanks also to Chris for his help in providing +understanding as to what this device was actually doing. + +This commit includes a test harness for the opvp +device, which uses the device client API to write +out the commands it receives to a text file for +comparison. To build the driver use ./build_opv_harness.sh +To use the driver use a command line like +-sDEVICE=opvp -sDriver=libopv.so -o output.txt -f ./examples/tiger.eps +The command lines are always dumped to the same +file which is opvp_command_dump.txt. Note that the +harness itself has to rely upon globals due to our +inability to change the client API. + +CVE: CVE-2024-33871 + +Upstream-Status: Backport [https://github.com/ArtifexSoftware/ghostpdl/commit/8b47f269b83b172b22606] + +Signed-off-by: Archana Polampalli +--- + contrib/opvp/README.txt | 18 + + contrib/opvp/build_opv_harness.sh | 4 + + contrib/opvp/gdevopvp.c | 1879 +++++++++++++++++------------ + contrib/opvp/opvp.h | 9 +- + contrib/opvp/opvp_0_2_0.h | 4 +- + contrib/opvp/opvpharness.c | 947 +++++++++++++++ + 6 files changed, 2070 insertions(+), 791 deletions(-) + create mode 100644 contrib/opvp/README.txt + create mode 100755 contrib/opvp/build_opv_harness.sh + create mode 100644 contrib/opvp/opvpharness.c + +diff --git a/contrib/opvp/README.txt b/contrib/opvp/README.txt +new file mode 100644 +index 0000000..fd2250e +--- /dev/null ++++ b/contrib/opvp/README.txt +@@ -0,0 +1,18 @@ ++In an effort to remove globals in devices ++that ship with Ghostscript, the opvp device was updated ++to place it's global values into the device structure. ++ ++As part of that commit, a harness was added to enable ++testing of the opvp device client API to test for any ++issues. To build the harness use ./build_opv_harness.sh ++This will create a debug version of the shared object ++libopv.so. The command line ++gs -sDEVICE=opvp -sDriver=./contrib/opvp/libopv.so -o output.txt -f ./examples/tiger.eps ++can then be used. ++ ++This command should create a file called ++opvp_command_dump.txt that contains the calls and ++the parameters made to the client API. Note that the ++harness itself has to rely upon globals. To do otherwise ++would require a to change the client API, which we ++do not own. +\ No newline at end of file +diff --git a/contrib/opvp/build_opv_harness.sh b/contrib/opvp/build_opv_harness.sh +new file mode 100755 +index 0000000..8d10f05 +--- /dev/null ++++ b/contrib/opvp/build_opv_harness.sh +@@ -0,0 +1,4 @@ ++#!/bin/bash ++ ++gcc -Werror -Wall -c -fpic -g opvpharness.c ++gcc -shared -o libopv.so opvpharness.o +\ No newline at end of file +diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c +index 844b46c..64afbfe 100644 +--- a/contrib/opvp/gdevopvp.c ++++ b/contrib/opvp/gdevopvp.c +@@ -115,14 +115,62 @@ typedef struct { + + #define MAX_PATH_POINTS 1000 + +-/* driver */ +-typedef struct gx_device_opvp_s { ++/* To remove the existing globals from this device, ++ we place the current globals into a structure ++ and place them at the same offset location ++ for the opvp and oprp devices, allowing easy ++ access regardless of the device type. */ ++ ++typedef struct opXp_globals_s { ++ bool vector; ++ bool inkjet; ++ bool zoomAuto; ++ bool zooming; ++ bool beginPage; ++ float margins[4]; ++ float zoom[2]; ++ float shift[2]; ++ opvp_int_t outputFD; ++ opvp_int_t nApiEntry; ++ opvp_dc_t printerContext; ++ opvp_cspace_t colorSpace; ++ opvp_cspace_t savedColorSpace; ++ char* vectorDriver; ++ char* printerModel; ++ void* handle; ++ opvp_brush_t* vectorFillColor; ++ opvp_int_t* ErrorNo; ++ opvp_api_procs_t* apiEntry; ++ OPVP_api_procs* apiEntry_0_2; ++ char* jobInfo; ++ char* docInfo; ++ opvp_dc_t(*OpenPrinter)(opvp_int_t, const opvp_char_t*, ++ const opvp_int_t[2], opvp_api_procs_t**); ++ int (*OpenPrinter_0_2)(int, char*, int*, ++ OPVP_api_procs**); ++ int (*GetLastError)(gx_device*); ++} opXp_globals; ++ ++typedef struct base_opvp_s { + gx_device_vector_common; ++} base_opvp; ++ ++typedef struct base_oprp_s { ++ gx_device_common; ++ gx_prn_device_common; ++} base_oprp; ++ ++typedef struct gx_device_opvp_s { ++ gx_device_vector_common; ++ char padding[1 + (sizeof(base_oprp) > sizeof(base_opvp) ? sizeof(base_oprp) - sizeof(base_opvp) : 0)]; ++ opXp_globals globals; + } gx_device_opvp; + +-typedef struct gx_device_oprp_s { ++typedef struct gx_device_oprp_s { + gx_device_common; + gx_prn_device_common; ++ char padding[1 + (sizeof(base_opvp) > sizeof(base_oprp) ? sizeof(base_opvp) - sizeof(base_oprp) : 0)]; ++ opXp_globals globals; + } gx_device_oprp; + + /* point (internal) */ +@@ -135,15 +183,16 @@ typedef struct { + + /* Utilities */ + static int opvp_startpage(gx_device *); +-static int opvp_endpage(void); ++static int opvp_endpage(gx_device*); + 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_gen_dynamic_lib_name(gx_device*); + static char *opvp_to_utf8(char *); +-#define opvp_check_in_page(pdev) \ +- ((beginPage) || (inkjet) ? 0 \ +- : (*vdev_proc(pdev, beginpage))((gx_device_vector*)pdev)) ++#define opvp_check_in_page(opdev) \ ++ ((((gx_device_opvp*)(opdev))->globals.beginPage) || \ ++ (((gx_device_opvp*)(opdev))->globals.inkjet) ? 0 \ ++ : (*vdev_proc(opdev, beginpage))((gx_device_vector*)opdev)) + 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 *);*/ +@@ -160,8 +209,8 @@ 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 opvp_load_vector_driver(gx_device*); ++static int opvp_unload_vector_driver(gx_device*); + static int prepare_open(gx_device *); + + /* driver procs */ +@@ -177,10 +226,10 @@ static int opvp_copy_mono(gx_device *, const byte *, 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 _get_params(gx_device*, 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 _put_params(gx_device*, 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_gstate *, gx_path *, +@@ -295,6 +344,53 @@ gs_public_st_suffix_add0_final( + NULL, /* *jobInfo */\ + NULL /* *docInfo */ + ++ ++static int ++GetLastError_1_0(gx_device* dev) ++{ ++ gx_device_opvp* pdev = (gx_device_opvp*)dev; ++ ++ return *(pdev->globals.ErrorNo); ++} ++ ++/* Initialize the globals */ ++static void ++InitGlobals(gx_device* dev) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ opdev->globals.vector = true; ++ opdev->globals.inkjet = false; ++ opdev->globals.zoomAuto = false; ++ opdev->globals.zooming = false; ++ opdev->globals.beginPage = false; ++ opdev->globals.margins[0] = 0; ++ opdev->globals.margins[1] = 0; ++ opdev->globals.margins[2] = 0; ++ opdev->globals.margins[3] = 0; ++ opdev->globals.zoom[0] = 1; ++ opdev->globals.zoom[1] = 1; ++ opdev->globals.shift[0] = 0; ++ opdev->globals.shift[1] = 0; ++ opdev->globals.outputFD = -1; ++ opdev->globals.nApiEntry = 0; ++ opdev->globals.printerContext = -1; ++ opdev->globals.colorSpace = OPVP_CSPACE_STANDARDRGB; ++ opdev->globals.savedColorSpace = OPVP_CSPACE_STANDARDRGB; ++ opdev->globals.vectorDriver = NULL; ++ opdev->globals.printerModel = NULL; ++ opdev->globals.handle = NULL; ++ opdev->globals.vectorFillColor = NULL; ++ opdev->globals.ErrorNo = NULL; ++ opdev->globals.apiEntry = NULL; ++ opdev->globals.apiEntry_0_2 = NULL; ++ opdev->globals.jobInfo = NULL; ++ opdev->globals.docInfo = NULL; ++ opdev->globals.OpenPrinter = NULL; ++ opdev->globals.OpenPrinter_0_2 = NULL; ++ opdev->globals.GetLastError = GetLastError_1_0; ++} ++ + /* device procs */ + static void + opvp_initialize_device_procs(gx_device *dev) +@@ -325,6 +421,9 @@ opvp_initialize_device_procs(gx_device *dev) + * by the system to the default. For compatibility we do the same. */ + set_dev_proc(dev, encode_color, NULL); + set_dev_proc(dev, decode_color, NULL); ++ ++ /* And the device globals */ ++ InitGlobals(dev); + } + + /* vector procs */ +@@ -394,6 +493,9 @@ oprp_initialize_device_procs(gx_device *dev) + * by the system to the default. For compatibility we do the same. */ + set_dev_proc(dev, encode_color, NULL); + set_dev_proc(dev, decode_color, NULL); ++ ++ /* And the device globals */ ++ InitGlobals(dev); + } + + const gx_device_oprp gs_oprp_device = +@@ -412,43 +514,6 @@ const gx_device_oprp gs_oprp_device = + ) + }; + +-/* 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 */ +@@ -496,9 +561,11 @@ static int colorDepth_0_2[] = { + + /* translate error code */ + static int +-GetLastError_0_2(void) ++GetLastError_0_2(gx_device* dev) + { +- switch(*ErrorNo) { ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ switch(*(opdev->globals.ErrorNo)) { + case OPVP_FATALERROR_0_2: + return OPVP_FATALERROR; + break; +@@ -526,48 +593,51 @@ GetLastError_0_2(void) + } + + static opvp_result_t +-StartPageWrapper(opvp_dc_t printerContext, const opvp_char_t *pageInfo) ++StartPageWrapper(gx_device *dev, opvp_dc_t printerContext, const opvp_char_t *pageInfo) + { + int r; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if ((r = apiEntry_0_2->StartPage(printerContext, ++ if ((r = opdev->globals.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, ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_P); + } + return OPVP_OK; + } + + static opvp_result_t +-InitGSWrapper(opvp_dc_t printerContext) ++InitGSWrapper(gx_device *dev, opvp_dc_t printerContext) + { + int r; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if ((r = apiEntry_0_2->InitGS(printerContext)) != OPVP_OK) { ++ if ((r = opdev->globals.apiEntry_0_2->InitGS(printerContext)) != OPVP_OK) { + /* error */ + return r; + } + /* initialize ROP */ +- if (apiEntry_0_2->SetROP != NULL) { +- apiEntry_0_2->SetROP(printerContext, ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.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, ++QueryColorSpaceWrapper(gx_device *dev, opvp_dc_t printerContext, opvp_int_t *pnum, + opvp_cspace_t *pcspace) + { + int r; + int i; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if ((r = apiEntry_0_2->QueryColorSpace(printerContext, ++ if ((r = opdev->globals.apiEntry_0_2->QueryColorSpace(printerContext, + (OPVP_ColorSpace *)pcspace,pnum)) != OPVP_OK) { + /* error */ + return r; +@@ -587,51 +657,54 @@ QueryColorSpaceWrapper( opvp_dc_t printerContext, opvp_int_t *pnum, + } + + static opvp_result_t +-SetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t cspace) ++SetColorSpaceWrapper(gx_device *dev, opvp_dc_t printerContext, opvp_cspace_t cspace) + { ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ + if (cspace == OPVP_CSPACE_DEVICEKRGB) { + /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ +- *ErrorNo = OPVP_NOTSUPPORTED_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_NOTSUPPORTED_0_2; + return -1; + } + if ((int)cspace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } +- return apiEntry_0_2->SetColorSpace(printerContext, ++ return opdev->globals.apiEntry_0_2->SetColorSpace(printerContext, + cspace_1_0_to_0_2[cspace]); + } + ++/* Not used + static opvp_result_t +-GetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t *pcspace) ++GetColorSpaceWrapper(gx_device *dev, opvp_dc_t printerContext, opvp_cspace_t *pcspace) + { + int r; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if ((r = apiEntry_0_2->GetColorSpace(printerContext, ++ if ((r = opdev->globals.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) ++SetStrokeColorWrapper(gx_device *dev, opvp_dc_t printerContext, const opvp_brush_t *brush) + { + OPVP_Brush brush_0_2; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + if (brush == NULL) { +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } + if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) { +@@ -641,7 +714,7 @@ SetStrokeColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) + if ((int)brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; +@@ -649,16 +722,17 @@ SetStrokeColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) + 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); ++ return opdev->globals.apiEntry_0_2->SetStrokeColor(printerContext, &brush_0_2); + } + + static opvp_result_t +-SetFillColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) ++SetFillColorWrapper(gx_device *dev, opvp_dc_t printerContext, const opvp_brush_t *brush) + { + OPVP_Brush brush_0_2; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + if (brush == NULL) { +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } + if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) { +@@ -668,7 +742,7 @@ SetFillColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) + if ((int)brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; +@@ -676,27 +750,28 @@ SetFillColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) + 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); ++ return opdev->globals.apiEntry_0_2->SetFillColor(printerContext, &brush_0_2); + } + + static opvp_result_t +-SetBgColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) ++SetBgColorWrapper(gx_device *dev, opvp_dc_t printerContext, const opvp_brush_t *brush) + { + OPVP_Brush brush_0_2; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + if (brush == NULL) { +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.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; ++ *(opdev->globals.ErrorNo) = OPVP_NOTSUPPORTED_0_2; + return -1; + } + if ((int)brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ +- *ErrorNo = OPVP_PARAMERROR_0_2; ++ *(opdev->globals.ErrorNo) = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; +@@ -704,11 +779,12 @@ SetBgColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) + 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); ++ return opdev->globals.apiEntry_0_2->SetBgColor(printerContext, &brush_0_2); + } + + static opvp_result_t + DrawImageWrapper( ++ gx_device *dev, + opvp_dc_t printerContext, + opvp_int_t sourceWidth, + opvp_int_t sourceHeight, +@@ -723,30 +799,31 @@ DrawImageWrapper( + OPVP_ImageFormat iformat_0_2; + OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent; + int depth; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + if (imageFormat == OPVP_IFORMAT_MASK) { +- if (apiEntry_0_2->GetPaintMode != NULL) { +- apiEntry_0_2->GetPaintMode(printerContext, ++ if (opdev->globals.apiEntry_0_2->GetPaintMode != NULL) { ++ opdev->globals.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, ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_S); + } + } + else { +- if (apiEntry_0_2->SetROP != NULL) { +- apiEntry_0_2->SetROP(printerContext, ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S); + } +- depth = colorDepth_0_2[colorSpace]; ++ depth = colorDepth_0_2[opdev->globals.colorSpace]; + } + + OPVP_I2FIX(0,rect.p0.x); +@@ -755,17 +832,17 @@ DrawImageWrapper( + 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; ++ *(opdev->globals.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, ++ r = opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P); + } + + return r; +@@ -773,6 +850,7 @@ DrawImageWrapper( + + static opvp_result_t + StartDrawImageWrapper( ++ gx_device *dev, + opvp_dc_t printerContext, + opvp_int_t sourceWidth, + opvp_int_t sourceHeight, +@@ -786,28 +864,29 @@ StartDrawImageWrapper( + OPVP_ImageFormat iformat_0_2; + OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent; + int depth; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + if (imageFormat == OPVP_IFORMAT_MASK) { +- if (apiEntry_0_2->GetPaintMode != NULL) { +- apiEntry_0_2->GetPaintMode(printerContext, ++ if (opdev->globals.apiEntry_0_2->GetPaintMode != NULL) { ++ opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S); + } +- depth = colorDepth_0_2[colorSpace]; ++ depth = colorDepth_0_2[opdev->globals.colorSpace]; + } + + OPVP_I2FIX(0,rect.p0.x); +@@ -816,310 +895,518 @@ StartDrawImageWrapper( + 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; ++ *(opdev->globals.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); ++ r = opdev->globals.apiEntry_0_2->StartDrawImage(printerContext, ++ sourceWidth, sourceHeight, ++ depth, iformat_0_2, rect); + + return r; + } + + static opvp_result_t +-EndDrawImageWrapper(opvp_dc_t printerContext) ++EndDrawImageWrapper(gx_device *dev, opvp_dc_t printerContext) + { + int r; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- r = apiEntry_0_2->EndDrawImage(printerContext); ++ r = opdev->globals.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); ++ if (opdev->globals.apiEntry_0_2->SetROP != NULL) { ++ opdev->globals.apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P); + } + + return r; + } + ++/* Not used + static opvp_result_t + QueryDeviceCapabilityWrapper( ++ gx_device *dev, + opvp_dc_t printerContext, + opvp_queryinfoflags_t queryflag, + opvp_int_t *buflen, + opvp_char_t *infoBuf) + { +- return apiEntry_0_2->QueryDeviceCapability(printerContext,queryflag, ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ return opdev->globals.apiEntry_0_2->QueryDeviceCapability(printerContext,queryflag, + *buflen,(char *)infoBuf); + } + + static opvp_result_t + QueryDeviceInfoWrapper( ++ gx_device *dev, + opvp_dc_t printerContext, + opvp_queryinfoflags_t queryflag, + opvp_int_t *buflen, + opvp_char_t *infoBuf) + { ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ + if (queryflag & OPVP_QF_MEDIACOPY) { +- *ErrorNo = OPVP_NOTSUPPORTED; ++ *(opdev->globals.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); ++ return opdev->globals.apiEntry_0_2->QueryDeviceInfo(printerContext, queryflag, ++ *buflen, (char *)infoBuf); + } ++*/ + + static opvp_result_t +-SetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t num, ++SetLineDashWrapper(gx_device *dev, 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); ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ return opdev->globals.apiEntry_0_2->SetLineDash(printerContext, num, ++ /* remove const */ (OPVP_Fix *)pdash); + } + ++/* Not used + static opvp_result_t +-GetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t *pnum, ++GetLineDashWrapper(gx_device* dev, opvp_dc_t printerContext, opvp_int_t *pnum, + opvp_fix_t *pdash) + { +- return apiEntry_0_2->GetLineDash(printerContext, ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ return opdev->globals.apiEntry_0_2->GetLineDash(printerContext, + pdash,pnum); + } ++*/ + + static opvp_dc_t + OpenPrinterWrapper( ++ gx_device *dev, + opvp_int_t outputFD, + const opvp_char_t *printerModel, + const opvp_int_t apiVersion[2], + opvp_api_procs_t **apiProcs) + { ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ + opvp_dc_t dc = -1; + +- if (OpenPrinter != NULL) { +- dc = (*OpenPrinter)(outputFD,printerModel,apiVersion,apiProcs); ++ if (opdev->globals.OpenPrinter != NULL) { ++ dc = (*(opdev->globals.OpenPrinter))(outputFD, printerModel, apiVersion, apiProcs); + } else { + /* try version 0.2 */ + +- if (OpenPrinter_0_2 != NULL) { ++ if (opdev->globals.OpenPrinter_0_2 != NULL) { + static opvp_api_procs_t tEntry; +- int nApiEntry; ++ int nApiEntry; /* Alias with prior global. Kept as is */ + +- dc = (*OpenPrinter_0_2)(outputFD, ++ dc = (*(opdev->globals.OpenPrinter_0_2))(outputFD, + /* remove const */ + (char *)printerModel, +- &nApiEntry,&apiEntry_0_2); ++ &nApiEntry, ++ &(opdev->globals.apiEntry_0_2)); + /* setting functions */ + tEntry.opvpClosePrinter +- = apiEntry_0_2->ClosePrinter; ++ = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->StartJob; ++ tEntry.opvpEndJob = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->StartDoc; ++ tEntry.opvpEndDoc = opdev->globals.apiEntry_0_2->EndDoc; ++ tEntry.opvpStartPage = NULL; ++ tEntry.opvpEndPage = opdev->globals.apiEntry_0_2->EndPage; ++ tEntry.opvpQueryDeviceCapability = NULL; ++ tEntry.opvpQueryDeviceInfo = NULL; ++ tEntry.opvpResetCTM = opdev->globals.apiEntry_0_2->ResetCTM; + tEntry.opvpSetCTM = (opvp_result_t (*)(opvp_dc_t, + const opvp_ctm_t*)) +- apiEntry_0_2->SetCTM; ++ opdev->globals.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; +- } ++ opdev->globals.apiEntry_0_2->GetCTM; ++ tEntry.opvpInitGS = NULL; ++ tEntry.opvpSaveGS = opdev->globals.apiEntry_0_2->SaveGS; ++ tEntry.opvpRestoreGS = opdev->globals.apiEntry_0_2->RestoreGS; ++ tEntry.opvpQueryColorSpace = NULL; ++ tEntry.opvpSetColorSpace = NULL; ++ tEntry.opvpGetColorSpace = NULL; ++ + tEntry.opvpSetFillMode + = (opvp_result_t (*)(opvp_dc_t,opvp_fillmode_t)) +- apiEntry_0_2->SetFillMode; ++ opdev->globals.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; +- } ++ opdev->globals.apiEntry_0_2->GetFillMode; ++ tEntry.opvpSetAlphaConstant = opdev->globals.apiEntry_0_2->SetAlphaConstant; ++ tEntry.opvpGetAlphaConstant = opdev->globals.apiEntry_0_2->GetAlphaConstant; ++ tEntry.opvpSetLineWidth = opdev->globals.apiEntry_0_2->SetLineWidth; ++ tEntry.opvpGetLineWidth = opdev->globals.apiEntry_0_2->GetLineWidth; ++ tEntry.opvpSetLineDash = NULL; ++ tEntry.opvpGetLineDash = NULL; ++ + tEntry.opvpSetLineDashOffset +- = apiEntry_0_2->SetLineDashOffset; ++ = opdev->globals.apiEntry_0_2->SetLineDashOffset; + tEntry.opvpGetLineDashOffset +- = apiEntry_0_2->GetLineDashOffset; ++ = opdev->globals.apiEntry_0_2->GetLineDashOffset; + tEntry.opvpSetLineStyle + = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t)) +- apiEntry_0_2->SetLineStyle; ++ opdev->globals.apiEntry_0_2->SetLineStyle; + tEntry.opvpGetLineStyle + = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t*)) +- apiEntry_0_2->GetLineStyle; ++ opdev->globals.apiEntry_0_2->GetLineStyle; + tEntry.opvpSetLineCap + = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t)) +- apiEntry_0_2->SetLineCap; ++ opdev->globals.apiEntry_0_2->SetLineCap; + tEntry.opvpGetLineCap + = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t*)) +- apiEntry_0_2->GetLineCap; ++ opdev->globals.apiEntry_0_2->GetLineCap; + tEntry.opvpSetLineJoin + = (opvp_result_t (*)(opvp_dc_t,opvp_linejoin_t)) +- apiEntry_0_2->SetLineJoin; ++ opdev->globals.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; ++ opdev->globals.apiEntry_0_2->GetLineJoin; ++ tEntry.opvpSetMiterLimit = opdev->globals.apiEntry_0_2->SetMiterLimit; ++ tEntry.opvpGetMiterLimit = opdev->globals.apiEntry_0_2->GetMiterLimit; + tEntry.opvpSetPaintMode + = (opvp_result_t (*)(opvp_dc_t,opvp_paintmode_t)) +- apiEntry_0_2->SetPaintMode; ++ opdev->globals.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; ++ opdev->globals.apiEntry_0_2->GetPaintMode; ++ tEntry.opvpSetStrokeColor = NULL; ++ tEntry.opvpSetFillColor = NULL; ++ tEntry.opvpSetBgColor = NULL; ++ tEntry.opvpNewPath = opdev->globals.apiEntry_0_2->NewPath; ++ tEntry.opvpEndPath = opdev->globals.apiEntry_0_2->EndPath; ++ tEntry.opvpStrokePath = opdev->globals.apiEntry_0_2->StrokePath; ++ tEntry.opvpFillPath = opdev->globals.apiEntry_0_2->FillPath; ++ tEntry.opvpStrokeFillPath = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->SetClipPath; ++ tEntry.opvpResetClipPath = opdev->globals.apiEntry_0_2->ResetClipPath; ++ tEntry.opvpSetCurrentPoint = opdev->globals.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; ++ opdev->globals.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; ++ opdev->globals.apiEntry_0_2->PolygonPath; + tEntry.opvpRectanglePath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_rectangle_t*)) +- apiEntry_0_2->RectanglePath; ++ opdev->globals.apiEntry_0_2->RectanglePath; + tEntry.opvpRoundRectanglePath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_roundrectangle_t*)) +- apiEntry_0_2->RoundRectanglePath; ++ opdev->globals.apiEntry_0_2->RoundRectanglePath; + tEntry.opvpBezierPath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_point_t*)) +- apiEntry_0_2->BezierPath; ++ opdev->globals.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; +- } ++ opvp_fix_t))opdev->globals.apiEntry_0_2->ArcPath; ++ tEntry.opvpDrawImage = NULL; ++ 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; ++ opdev->globals.apiEntry_0_2->TransferDrawImage; ++ tEntry.opvpEndDrawImage = NULL; ++ tEntry.opvpStartScanline = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->Scanline; ++ tEntry.opvpEndScanline = opdev->globals.apiEntry_0_2->EndScanline; ++ tEntry.opvpStartRaster = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->TransferRasterData; ++ tEntry.opvpSkipRaster = opdev->globals.apiEntry_0_2->SkipRaster; ++ tEntry.opvpEndRaster = opdev->globals.apiEntry_0_2->EndRaster; ++ tEntry.opvpStartStream = opdev->globals.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; ++ opdev->globals.apiEntry_0_2->TransferStreamData; ++ tEntry.opvpEndStream = opdev->globals.apiEntry_0_2->EndStream; + + *apiProcs = &tEntry; + +- GetLastError = GetLastError_0_2; ++ opdev->globals.GetLastError = GetLastError_0_2; + } + } + return dc; + } + ++/* Set of methods to separate the 0.2 and 1.0 calls AND deal with the prior use of globals */ ++static opvp_result_t ++gsopvpStartPage(gx_device* dev, opvp_dc_t printerContext, const opvp_char_t* pageInfo) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->StartPage) { ++ return StartPageWrapper(dev, printerContext, pageInfo); ++ } else if (opdev->globals.apiEntry->opvpStartPage) { ++ return opdev->globals.apiEntry->opvpStartPage(printerContext, pageInfo); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++/* Not used ++static opvp_result_t ++gsopvpQueryDeviceCapability( ++ gx_device* dev, ++ opvp_dc_t printerContext, ++ opvp_queryinfoflags_t queryflag, ++ opvp_int_t* buflen, ++ opvp_char_t* infoBuf) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->QueryDeviceCapability) { ++ return QueryDeviceCapabilityWrapper(dev, printerContext, queryflag, buflen, infoBuf); ++ } else if (opdev->globals.apiEntry->opvpQueryDeviceCapability) { ++ return opdev->globals.apiEntry->opvpQueryDeviceCapability(printerContext, queryflag, buflen, infoBuf); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpQueryDeviceInfo( ++ gx_device* dev, ++ opvp_dc_t printerContext, ++ opvp_queryinfoflags_t queryflag, ++ opvp_int_t* buflen, ++ opvp_char_t* infoBuf) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->QueryDeviceCapability) { ++ return QueryDeviceInfoWrapper(dev, printerContext, queryflag, buflen, infoBuf); ++ } else if (opdev->globals.apiEntry->opvpQueryDeviceCapability) { ++ return opdev->globals.apiEntry->opvpQueryDeviceInfo(printerContext, queryflag, buflen, infoBuf); ++ } else ++ return OPVP_FATALERROR; ++} ++*/ ++ ++static opvp_result_t ++gsopvpInitGS(gx_device* dev, opvp_dc_t printerContext) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->InitGS) { ++ return InitGSWrapper(dev, printerContext); ++ } else if (opdev->globals.apiEntry->opvpInitGS) { ++ return opdev->globals.apiEntry->opvpInitGS(printerContext); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpQueryColorSpace(gx_device* dev, opvp_dc_t printerContext, opvp_int_t* pnum, ++ opvp_cspace_t* pcspace) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->QueryColorSpace) { ++ return QueryColorSpaceWrapper(dev, printerContext, pnum, pcspace); ++ } else if (opdev->globals.apiEntry->opvpQueryColorSpace) { ++ return opdev->globals.apiEntry->opvpQueryColorSpace(printerContext, pnum, pcspace); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpSetColorSpace(gx_device* dev, opvp_dc_t printerContext, opvp_cspace_t cspace) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->SetColorSpace) { ++ return SetColorSpaceWrapper(dev, printerContext, cspace); ++ } else if (opdev->globals.apiEntry->opvpQueryColorSpace) { ++ return opdev->globals.apiEntry->opvpSetColorSpace(printerContext, cspace); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++/* Not used ++static opvp_result_t ++gsopvpGetColorSpace(gx_device* dev, opvp_dc_t printerContext, opvp_cspace_t* pcspace) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->GetColorSpace) { ++ return GetColorSpaceWrapper(dev, printerContext, pcspace); ++ } else if (opdev->globals.apiEntry->opvpGetColorSpace) { ++ return opdev->globals.apiEntry->opvpGetColorSpace(printerContext, pcspace); ++ } else ++ return OPVP_FATALERROR; ++} ++*/ ++ ++static opvp_result_t ++gsopvpSetLineDash(gx_device* dev, opvp_dc_t printerContext, opvp_int_t num, ++ const opvp_fix_t* pdash) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->SetLineDash) { ++ return SetLineDashWrapper(dev, printerContext, num, pdash); ++ } else if (opdev->globals.apiEntry->opvpSetLineDash) { ++ return opdev->globals.apiEntry->opvpSetLineDash(printerContext, num, pdash); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++/* Not used ++static opvp_result_t ++gsopvpGetLineDash(gx_device* dev, opvp_dc_t printerContext, opvp_int_t* pnum, ++ opvp_fix_t* pdash) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->GetLineDash) { ++ return GetLineDashWrapper(dev, printerContext, pnum, pdash); ++ } else if (opdev->globals.apiEntry->opvpGetLineDash) { ++ return opdev->globals.apiEntry->opvpGetLineDash(printerContext, pnum, pdash); ++ } else ++ return OPVP_FATALERROR; ++} ++*/ ++ ++static opvp_result_t ++gsopvpSetStrokeColor(gx_device* dev, opvp_dc_t printerContext, const opvp_brush_t* brush) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->SetStrokeColor) { ++ return SetStrokeColorWrapper(dev, printerContext, brush); ++ } else if (opdev->globals.apiEntry->opvpSetStrokeColor) { ++ return opdev->globals.apiEntry->opvpSetStrokeColor(printerContext, brush); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpSetFillColor(gx_device* dev, opvp_dc_t printerContext, const opvp_brush_t* brush) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->SetFillColor) { ++ return SetFillColorWrapper(dev, printerContext, brush); ++ } else if (opdev->globals.apiEntry->opvpSetFillColor) { ++ return opdev->globals.apiEntry->opvpSetFillColor(printerContext, brush); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpSetBgColor(gx_device* dev, opvp_dc_t printerContext, const opvp_brush_t* brush) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->SetBgColor) { ++ return SetBgColorWrapper(dev, printerContext, brush); ++ } else if (opdev->globals.apiEntry->opvpSetBgColor) { ++ return opdev->globals.apiEntry->opvpSetBgColor(printerContext, brush); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpDrawImage( ++ gx_device* dev, ++ 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) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->DrawImage) { ++ return DrawImageWrapper(dev, printerContext, sourceWidth, sourceHeight, ++ sourcePitch, imageFormat, destinationWidth, destinationHeight, imagedata); ++ } else if (opdev->globals.apiEntry->opvpDrawImage) { ++ return opdev->globals.apiEntry->opvpDrawImage(printerContext, sourceWidth, sourceHeight, ++ sourcePitch, imageFormat, destinationWidth, destinationHeight, imagedata); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpStartDrawImage( ++ gx_device* dev, ++ 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) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->StartDrawImage) { ++ return StartDrawImageWrapper(dev, printerContext, sourceWidth, sourceHeight, ++ sourcePitch, imageFormat, destinationWidth, destinationHeight); ++ } else if (opdev->globals.apiEntry->opvpStartDrawImage) { ++ return opdev->globals.apiEntry->opvpStartDrawImage(printerContext, sourceWidth, sourceHeight, ++ sourcePitch, imageFormat, destinationWidth, destinationHeight); ++ } else ++ return OPVP_FATALERROR; ++} ++ ++static opvp_result_t ++gsopvpEndDrawImage(gx_device* dev, opvp_dc_t printerContext) ++{ ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.apiEntry_0_2 != NULL && ++ opdev->globals.apiEntry_0_2->EndDrawImage) { ++ return EndDrawImageWrapper(dev, printerContext); ++ } else if (opdev->globals.apiEntry->opvpEndDrawImage) { ++ return opdev->globals.apiEntry->opvpEndDrawImage(printerContext); ++ } else ++ return OPVP_FATALERROR; ++} ++ + /* for image */ + static const + gx_image_enum_procs_t opvp_image_enum_procs = +@@ -1167,27 +1454,28 @@ typedef struct bbox_image_enum_s { + /* initialize Graphic State */ + /* No defaults in OPVP 1.0 */ + static int +-InitGS(void) ++InitGS(gx_device* dev) + { +- if (apiEntry->opvpInitGS != NULL) { +- if (apiEntry->opvpInitGS(printerContext) != OPVP_OK) { +- return -1; +- } ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ if (gsopvpInitGS(dev, opdev->globals.printerContext) != OPVP_OK) { ++ return -1; + } +- if (apiEntry->opvpSetColorSpace != NULL) { +- if (apiEntry->opvpSetColorSpace(printerContext,colorSpace) +- != OPVP_OK) { ++ ++ if (opdev->globals.apiEntry->opvpSetColorSpace != NULL) { ++ if (opdev->globals.apiEntry->opvpSetColorSpace(opdev->globals.printerContext, ++ opdev->globals.colorSpace) != OPVP_OK){ + return -1; + } + } +- if (apiEntry->opvpSetPaintMode != NULL) { +- if (apiEntry->opvpSetPaintMode(printerContext, ++ if (opdev->globals.apiEntry->opvpSetPaintMode != NULL) { ++ if (opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.printerContext, + OPVP_PAINTMODE_TRANSPARENT) != OPVP_OK) { + return -1; + } + } +- if (apiEntry->opvpSetAlphaConstant != NULL) { +- if (apiEntry->opvpSetAlphaConstant(printerContext,1.0) ++ if (opdev->globals.apiEntry->opvpSetAlphaConstant != NULL) { ++ if (opdev->globals.apiEntry->opvpSetAlphaConstant(opdev->globals.printerContext,1.0) + != OPVP_OK) { + return -1; + } +@@ -1203,20 +1491,20 @@ opvp_startpage(gx_device *dev) + int ecode = 0; + opvp_result_t r = -1; + static char *page_info = NULL; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + /* 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 (opdev->globals.printerContext != -1) { ++ r = gsopvpStartPage(dev, opdev->globals.printerContext, ++ (opvp_char_t*)opvp_to_utf8(page_info)); + if (r != OPVP_OK) { + ecode = -1; + } else { +- ecode = InitGS(); ++ ecode = InitGS(dev); + } + } + +@@ -1224,15 +1512,16 @@ opvp_startpage(gx_device *dev) + } + + static int +-opvp_endpage(void) ++opvp_endpage(gx_device* dev) + { + int ecode = 0; + opvp_result_t r = -1; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + /* call EndPage */ +- if (printerContext != -1) { +- if (apiEntry->opvpEndPage) +- r = apiEntry->opvpEndPage(printerContext); ++ if (opdev->globals.printerContext != -1) { ++ if (opdev->globals.apiEntry->opvpEndPage) ++ r = opdev->globals.apiEntry->opvpEndPage(opdev->globals.printerContext); + if (r != OPVP_OK) { + ecode = -1; + } +@@ -1304,32 +1593,33 @@ opvp_adjust_num_string(char *num_string) + } + + static char ** +-opvp_gen_dynamic_lib_name(void) ++opvp_gen_dynamic_lib_name(gx_device* dev) + { + static char *buff[5] = {NULL,NULL,NULL,NULL,NULL}; + char tbuff[OPVP_BUFF_SIZE]; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if (!vectorDriver) { ++ if (!(opdev->globals.vectorDriver)) { + return NULL; + } + + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); +- strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 1); ++ strncpy(tbuff, opdev->globals.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); ++ strncpy(tbuff, opdev->globals.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); ++ strncpy(tbuff, opdev->globals.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); ++ strncat(tbuff, opdev->globals.vectorDriver, OPVP_BUFF_SIZE - 7); + strcat(tbuff, ".so"); + opvp_alloc_string(&(buff[3]), tbuff); + +@@ -1387,7 +1677,7 @@ opvp_to_utf8(char *string) + } + + static float +-opvp_fabsf(float f) ++opvp_fabsf(gx_device* dev, float f) + { + return (float)fabs((double)f); + } +@@ -1429,7 +1719,7 @@ opvp_get_papertable_index(gx_device *pdev) + paper = i; + match = true; + break; +- } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { ++ } else if ((f = opvp_fabsf(pdev, height - paper_h)) < TOLERANCE) { + if (f < h_delta) { + h_delta = f; + candidate = i; +@@ -1442,14 +1732,14 @@ opvp_get_papertable_index(gx_device *pdev) + } else if (prev != paper_w) { + prev = paper_w; + if (paper_w < width) { +- if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) { ++ if ((f = opvp_fabsf(pdev, width - paper_w)) < TOLERANCE) { + if (f < sw_delta) { + sw_delta = f; + smaller = i; + } + } + } else { +- if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) { ++ if ((f = opvp_fabsf(pdev, width - paper_w)) < TOLERANCE) { + if (f < lw_delta) { + lw_delta = f; + larger = i; +@@ -1468,7 +1758,7 @@ opvp_get_papertable_index(gx_device *pdev) + sh_delta = 0; + s_candi = i; + break; +- } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { ++ } else if ((f = opvp_fabsf(pdev, height - paper_h)) < TOLERANCE) { + if (f < sh_delta) { + sh_delta = f; + s_candi = i; +@@ -1484,7 +1774,7 @@ opvp_get_papertable_index(gx_device *pdev) + lh_delta = 0; + l_candi = i; + break; +- } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { ++ } else if ((f = opvp_fabsf(pdev, height - paper_h)) < TOLERANCE) { + if (f < lh_delta) { + lh_delta = f; + l_candi = i; +@@ -1560,8 +1850,8 @@ opvp_get_mediasize(gx_device *pdev) + (strcmp(region, "oe" ) == 0)) { + unit = "in"; + } else { +- width *= MMPI; +- height *= MMPI; ++ width *= (float) MMPI; ++ height *= (float) MMPI; + unit = "mm"; + } + } else { +@@ -1591,9 +1881,10 @@ opvp_gen_page_info(gx_device *dev) + int num_copies = 1; + bool landscape; + char tbuff[OPVP_BUFF_SIZE]; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + /* copies */ +- if (!inkjet) { ++ if (!(opdev->globals.inkjet)) { + if (dev->IgnoreNumCopies) { + num_copies = 1; + } else if (dev->NumCopies_set > 0) { +@@ -1642,14 +1933,13 @@ opvp_set_brush_color(gx_device_opvp *pdev, gx_color_index color, + ecode = -1; + } else { + #if ENABLE_SIMPLE_MODE +- brush->colorSpace = colorSpace; ++ brush->colorSpace = pdev->globals.colorSpace; + #else + opvp_result_t r = -1; + /* call GetColorSpace */ +- if (apiEntry->opvpGetColorSpace) { +- r = apiEntry->opvpGetColorSpace(printerContext, +- &(brush->colorSpace)); +- } ++ ++ r = gsopvpGetColorSpace((gx_device*)pdev, printerContext, ++ &(brush->colorSpace)); + if (r != OPVP_OK) { + brush->colorSpace = OPVP_CSPACE_DEVICEKRGB; + } +@@ -1667,7 +1957,7 @@ opvp_set_brush_color(gx_device_opvp *pdev, gx_color_index color, + + static int + opvp_draw_image( +- gx_device_opvp *pdev, ++ gx_device_opvp *opdev, + int depth, + int sw, + int sh, +@@ -1682,35 +1972,36 @@ opvp_draw_image( + int count; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ 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); +- } ++ r = gsopvpDrawImage((gx_device*) opdev, ++ opdev->globals.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); +- } ++ r = gsopvpStartDrawImage((gx_device*)opdev, ++ opdev->globals.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, ++ if (opdev->globals.apiEntry->opvpTransferDrawImage) { ++ r = opdev->globals.apiEntry->opvpTransferDrawImage( ++ opdev->globals.printerContext, + count, + /* discard 'const' qualifier */ + (void *)data); +@@ -1718,9 +2009,8 @@ opvp_draw_image( + if (r != OPVP_OK) ecode = -1; + + /* call EndDrawImage */ +- if (apiEntry->opvpEndDrawImage) { +- apiEntry->opvpEndDrawImage(printerContext); +- } ++ gsopvpEndDrawImage((gx_device*)opdev, opdev->globals.printerContext); ++ + } else { + ecode = 0; /* continue... */ + } +@@ -1735,48 +2025,49 @@ opvp_draw_image( + * load vector-driver + */ + static int +-opvp_load_vector_driver(void) ++opvp_load_vector_driver(gx_device* dev) + { + char **list = NULL; + int i; + void *h; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + +- if (handle) { +- opvp_unload_vector_driver(); ++ if (opdev->globals.handle) { ++ opvp_unload_vector_driver(dev); + } + +- if (vectorDriver) { +- list = opvp_gen_dynamic_lib_name(); ++ if (opdev->globals.vectorDriver) { ++ list = opvp_gen_dynamic_lib_name(dev); + } + + 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; ++ opdev->globals.OpenPrinter = dlsym(h,"opvpOpenPrinter"); ++ opdev->globals.ErrorNo = dlsym(h,"opvpErrorNo"); ++ if (opdev->globals.OpenPrinter && opdev->globals.ErrorNo) { ++ opdev->globals.handle = h; + break; + } +- OpenPrinter = NULL; +- ErrorNo = NULL; ++ opdev->globals.OpenPrinter = NULL; ++ opdev->globals.ErrorNo = NULL; + /* try version 0.2 driver */ +- OpenPrinter_0_2 = dlsym(h,"OpenPrinter"); +- ErrorNo = dlsym(h,"errorno"); +- if (OpenPrinter_0_2 && ErrorNo) { +- handle = h; ++ opdev->globals.OpenPrinter_0_2 = dlsym(h,"OpenPrinter"); ++ opdev->globals.ErrorNo = dlsym(h,"errorno"); ++ if (opdev->globals.OpenPrinter_0_2 && opdev->globals.ErrorNo) { ++ opdev->globals.handle = h; + break; + } +- OpenPrinter_0_2 = NULL; +- ErrorNo = NULL; ++ opdev->globals.OpenPrinter_0_2 = NULL; ++ opdev->globals.ErrorNo = NULL; + dlclose(h); + } + i++; + } + } + +- if (handle) { ++ if (opdev->globals.handle) { + return 0; + } else { + return -1; +@@ -1787,13 +2078,15 @@ opvp_load_vector_driver(void) + * unload vector-driver + */ + static int +-opvp_unload_vector_driver(void) ++opvp_unload_vector_driver(gx_device* dev) + { +- if (handle) { +- dlclose(handle); +- handle = NULL; +- OpenPrinter = NULL; +- ErrorNo = NULL; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; ++ ++ if (opdev->globals.handle) { ++ dlclose(opdev->globals.handle); ++ opdev->globals.handle = NULL; ++ opdev->globals.OpenPrinter = NULL; ++ opdev->globals.ErrorNo = NULL; + } + return 0; + } +@@ -1810,6 +2103,7 @@ prepare_open(gx_device *dev) + int dumFD = -1; + opvp_dc_t dumContext = -1; + opvp_cspace_t cspace = OPVP_CSPACE_STANDARDRGB; ++ gx_device_opvp *opdev = (gx_device_opvp*) dev; + + /* open dummy device */ + code = open("/dev/null", O_RDWR); +@@ -1818,19 +2112,19 @@ prepare_open(gx_device *dev) + + /* load vector driver */ + if (!ecode) { +- if ((code = opvp_load_vector_driver())) { ++ if ((code = opvp_load_vector_driver(dev))) { + ecode = code; + } + } + + /* prepare array of function pointer for PDAPI */ + if (!ecode) { +- if (!apiEntry) { +- if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { ++ if (!(opdev->globals.apiEntry)) { ++ if (!(opdev->globals.apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { + ecode = -1; + } + } else { +- memset(apiEntry, 0, sizeof(opvp_api_procs_t)); ++ memset(opdev->globals.apiEntry, 0, sizeof(opvp_api_procs_t)); + } + } + +@@ -1842,8 +2136,8 @@ prepare_open(gx_device *dev) + /* require version 1.0 */ + apiVersion[0] = 1; + apiVersion[1] = 0; +- dc = OpenPrinterWrapper(dumFD, (opvp_char_t *)printerModel, +- apiVersion,&api_entry); ++ dc = OpenPrinterWrapper(dev, dumFD, (opvp_char_t *)(opdev->globals.printerModel), ++ apiVersion, &api_entry); + if (dc == -1) { + ecode = -1; + } else { +@@ -1853,33 +2147,33 @@ prepare_open(gx_device *dev) + + /* set apiEntry */ + if (!ecode) { +- nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *); +- memcpy(apiEntry, api_entry, nApiEntry*sizeof(void *)); ++ opdev->globals.nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *); ++ memcpy(opdev->globals.apiEntry, api_entry, opdev->globals.nApiEntry*sizeof(void *)); + } else { +- if (apiEntry) free(apiEntry); +- apiEntry = NULL; ++ if (opdev->globals.apiEntry) free(opdev->globals.apiEntry); ++ opdev->globals.apiEntry = NULL; + } + + /* check vector fucntion */ +- if (apiEntry) { +- if (!inkjet) { +- if (!(apiEntry->opvpNewPath) || +- !(apiEntry->opvpEndPath) || +- !(apiEntry->opvpStrokePath) || +- !(apiEntry->opvpSetCurrentPoint) || +- !(apiEntry->opvpLinePath) || +- !(apiEntry->opvpBezierPath)) { ++ if (opdev->globals.apiEntry) { ++ if (!(opdev->globals.inkjet)) { ++ if (!(opdev->globals.apiEntry->opvpNewPath) || ++ !(opdev->globals.apiEntry->opvpEndPath) || ++ !(opdev->globals.apiEntry->opvpStrokePath) || ++ !(opdev->globals.apiEntry->opvpSetCurrentPoint) || ++ !(opdev->globals.apiEntry->opvpLinePath) || ++ !(opdev->globals.apiEntry->opvpBezierPath)) { + /* NOT avail vector drawing mode */ +- vector = false; ++ opdev->globals.vector = false; + } + } + /* call GetColorSpace */ +- if (apiEntry->opvpGetColorSpace) { +- (void)apiEntry->opvpGetColorSpace(dumContext, &cspace); ++ if (opdev->globals.apiEntry->opvpGetColorSpace) { ++ (void)(opdev->globals.apiEntry->opvpGetColorSpace)(dumContext, &cspace); + } + if (cspace == OPVP_CSPACE_BW) { + /* mono-color */ +- colorSpace = cspace; ++ opdev->globals.colorSpace = cspace; + dev->color_info.num_components = 1; + dev->color_info.depth = 1; + dev->color_info.max_gray = 0; +@@ -1888,7 +2182,7 @@ prepare_open(gx_device *dev) + dev->color_info.dither_colors = 1; + } else if (cspace == OPVP_CSPACE_DEVICEGRAY) { + /* gray-scale */ +- colorSpace = cspace; ++ opdev->globals.colorSpace = cspace; + dev->color_info.num_components = 1; + dev->color_info.depth = 8; + dev->color_info.max_gray = 255; +@@ -1897,7 +2191,7 @@ prepare_open(gx_device *dev) + dev->color_info.dither_colors = 256; + } else { + /* rgb color */ +- colorSpace = OPVP_CSPACE_STANDARDRGB; ++ opdev->globals.colorSpace = OPVP_CSPACE_STANDARDRGB; + dev->color_info.num_components = 3; + dev->color_info.depth = 24; + dev->color_info.max_gray = 255; +@@ -1913,8 +2207,8 @@ prepare_open(gx_device *dev) + /* call Closerinter as dummy */ + if (dumContext != -1) { + /* call ClosePrinter */ +- if (apiEntry->opvpClosePrinter) { +- apiEntry->opvpClosePrinter(dumContext); ++ if (opdev->globals.apiEntry->opvpClosePrinter) { ++ opdev->globals.apiEntry->opvpClosePrinter(dumContext); + } + dumContext = -1; + } +@@ -1926,7 +2220,7 @@ prepare_open(gx_device *dev) + } + + /* un-load vector driver */ +- opvp_unload_vector_driver(); ++ opvp_unload_vector_driver(dev); + + return ecode; + } +@@ -1961,51 +2255,52 @@ opvp_open(gx_device *dev) + } + + /* set margins */ +- if (zoomAuto) { +- margin_width = (margins[0] + margins[2]) ++ if (pdev->globals.zoomAuto) { ++ margin_width = (pdev->globals.margins[0] + pdev->globals.margins[2]) + * dev->HWResolution[0]; +- margin_height = (margins[1] + margins[3]) ++ margin_height = (pdev->globals.margins[1] + pdev->globals.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]; ++ pdev->globals.zoom[0] = (dev->width - margin_width) / dev->width; ++ pdev->globals.zoom[1] = (dev->height - margin_height) / dev->height; ++ if (pdev->globals.zoom[0] < pdev->globals.zoom[1]) { ++ pdev->globals.zoom[1] = pdev->globals.zoom[0]; + } else { +- zoom[0] = zoom[1]; ++ pdev->globals.zoom[0] = pdev->globals.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]) ++ if (pdev->globals.inkjet) { ++ if ((pdev->globals.margins[0] != 0) || ++ (pdev->globals.margins[1] != 0) || (pdev->globals.margins[3] != 0)) { ++ pdev->globals.shift[0] = pdev->globals.margins[0] * dev->HWResolution[0]; ++ pdev->globals.shift[1] = (pdev->globals.margins[1] + pdev->globals.margins[3]) + * dev->HWResolution[1]; +- zooming = true; ++ pdev->globals.zooming = true; + } +- dev->width -= margins[2] * dev->HWResolution[0]; +- dev->height -= margins[1] * dev->HWResolution[1]; ++ dev->width -= (int) (pdev->globals.margins[2] * dev->HWResolution[0]); ++ dev->height -= (int) (pdev->globals.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; ++ if ((pdev->globals.margins[0] != 0) || (pdev->globals.margins[1] != 0)) { ++ pdev->globals.shift[0] = pdev->globals.margins[0] * dev->HWResolution[0]; ++ pdev->globals.shift[1] = pdev->globals.margins[3] * dev->HWResolution[1]; ++ pdev->globals.zooming = true; + } + adj_margins[0] = 0; + adj_margins[3] = 0; +- adj_margins[1] = dev->height * zoom[1] / dev->HWResolution[1] ++ adj_margins[1] = dev->height * pdev->globals.zoom[1] / dev->HWResolution[1] + - (dev->MediaSize[1] / PS_DPI +- - (margins[1] + margins[3])); ++ - (pdev->globals.margins[1] + pdev->globals.margins[3])); + if (adj_margins[1] < 0) adj_margins[0] = 0; +- adj_margins[2] = dev->width * zoom[0] / dev->HWResolution[0] ++ adj_margins[2] = dev->width * pdev->globals.zoom[0] / dev->HWResolution[0] + - (dev->MediaSize[0] / PS_DPI +- - (margins[0] + margins[2])); ++ - (pdev->globals.margins[0] + pdev->globals.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; ++ if ((pdev->globals.zoom[0] != 1) || (pdev->globals.zoom[1] != 1)) ++ pdev->globals.zooming = true; + + /* open file for output device */ +- if (!inkjet) { ++ if (!(pdev->globals.inkjet)) { + pdev->v_memory = gs_memory_stable(pdev->memory); + /* open output stream */ + code = gdev_vector_open_file_options((gx_device_vector*)dev, +@@ -2027,7 +2322,7 @@ opvp_open(gx_device *dev) + pdev->bbox_device->memory = gs_memory_stable(dev->memory); + } + } +- outputFD = fileno(gp_get_file(pdev->file)); ++ pdev->globals.outputFD = fileno(gp_get_file(pdev->file)); + } else { + /* open printer device */ + code = gdev_prn_open(dev); +@@ -2044,13 +2339,13 @@ opvp_open(gx_device *dev) + if (code < 0) { + return code; + } +- outputFD = fileno(gp_get_file(rdev->file)); ++ pdev->globals.outputFD = fileno(gp_get_file(rdev->file)); + } +- if (outputFD < 0) +- return outputFD; ++ if (pdev->globals.outputFD < 0) ++ return pdev->globals.outputFD; + + /* RE-load vector driver */ +- if ((code = opvp_load_vector_driver())) { ++ if ((code = opvp_load_vector_driver(dev))) { + return code; + } + +@@ -2058,44 +2353,48 @@ opvp_open(gx_device *dev) + /* require version 1.0 */ + apiVersion[0] = 1; + apiVersion[1] = 0; +- dc = OpenPrinterWrapper(outputFD,(opvp_char_t *)printerModel, ++ dc = OpenPrinterWrapper(dev, pdev->globals.outputFD, (opvp_char_t *)pdev->globals.printerModel, + apiVersion,&api_entry); +- if (!apiEntry) { +- if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { ++ if (!(pdev->globals.apiEntry)) { ++ if (!(pdev->globals.apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { + ecode = -1; + } + } else { +- memset(apiEntry, 0, sizeof(opvp_api_procs_t)); ++ memset(pdev->globals.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); ++ if (pdev->globals.apiEntry) ++ free(pdev->globals.apiEntry); ++ pdev->globals.apiEntry = NULL; ++ opvp_unload_vector_driver(dev); ++ if (pdev->globals.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 *)); ++ pdev->globals.printerContext = dc; ++ pdev->globals.nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *); ++ memcpy(pdev->globals.apiEntry, api_entry, pdev->globals.nApiEntry*sizeof(void *)); + + /* initialize */ +- if ((!ecode) && (!inkjet)) { ++ if ((!ecode) && (!(pdev->globals.inkjet))) { + pdev->vec_procs = &opvp_vector_procs; +- if (vector) gdev_vector_init((gx_device_vector *)pdev); ++ if (pdev->globals.vector) ++ gdev_vector_init((gx_device_vector *)pdev); + } + +- if (apiEntry->opvpQueryColorSpace) { ++ if (pdev->globals.apiEntry->opvpQueryColorSpace || ++ pdev->globals.apiEntry_0_2->QueryColorSpace) { + 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)) ++ if ((r = gsopvpQueryColorSpace(dev, pdev->globals.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); ++ r = gsopvpQueryColorSpace(dev, pdev->globals.printerContext,&nn,p); + } + if (r == OPVP_OK) { + int i; +@@ -2111,12 +2410,12 @@ opvp_open(gx_device *dev) + /* start job */ + if (!ecode) { + /* job info */ +- if (jobInfo) { +- if (strlen(jobInfo) > 0) { +- job_info = opvp_alloc_string(&job_info,jobInfo); ++ if (pdev->globals.jobInfo) { ++ if (strlen(pdev->globals.jobInfo) > 0) { ++ job_info = opvp_alloc_string(&job_info, pdev->globals.jobInfo); + } + } +- tmp_info = opvp_alloc_string(&tmp_info,opvp_gen_job_info(dev)); ++ tmp_info = opvp_alloc_string(&tmp_info, opvp_gen_job_info(dev)); + if (tmp_info) { + if (strlen(tmp_info) > 0) { + if (job_info) { +@@ -2130,8 +2429,8 @@ opvp_open(gx_device *dev) + } + + /* call StartJob */ +- if (apiEntry->opvpStartJob) { +- r = apiEntry->opvpStartJob(printerContext, ++ if (pdev->globals.apiEntry->opvpStartJob) { ++ r = pdev->globals.apiEntry->opvpStartJob(pdev->globals.printerContext, + (opvp_char_t *)opvp_to_utf8(job_info)); + } + if (r != OPVP_OK) { +@@ -2142,9 +2441,9 @@ opvp_open(gx_device *dev) + /* start doc */ + if (!ecode) { + /* doc info */ +- if (docInfo) { +- if (strlen(docInfo) > 0) { +- doc_info = opvp_alloc_string(&doc_info,docInfo); ++ if (pdev->globals.docInfo) { ++ if (strlen(pdev->globals.docInfo) > 0) { ++ doc_info = opvp_alloc_string(&doc_info, pdev->globals.docInfo); + } + } + tmp_info = opvp_alloc_string(&tmp_info, opvp_gen_doc_info(dev)); +@@ -2161,8 +2460,8 @@ opvp_open(gx_device *dev) + } + + /* call StartDoc */ +- if (apiEntry->opvpStartDoc) { +- r = apiEntry->opvpStartDoc(printerContext, ++ if (pdev->globals.apiEntry->opvpStartDoc) { ++ r = pdev->globals.apiEntry->opvpStartDoc(pdev->globals.printerContext, + (opvp_char_t *)opvp_to_utf8(doc_info)); + } + if (r != OPVP_OK) { +@@ -2183,9 +2482,11 @@ opvp_open(gx_device *dev) + static int + oprp_open(gx_device *dev) + { ++ gx_device_opvp *opdev = (gx_device_opvp*) dev; ++ + /* set inkjet mode */ +- vector = false; +- inkjet = true; ++ opdev->globals.vector = false; ++ opdev->globals.inkjet = true; + + /* matrix */ + dev->procs.get_initial_matrix = opvp_get_initial_matrix; +@@ -2198,24 +2499,24 @@ oprp_open(gx_device *dev) + static void + opvp_get_initial_matrix(gx_device *dev, gs_matrix *pmat) + { +- gx_device_opvp *pdev = (gx_device_opvp *)dev; ++ gx_device_opvp * opdev = (gx_device_opvp *)dev; + opvp_ctm_t omat; + + gx_default_get_initial_matrix(dev,pmat); +- if (zooming) { ++ if (opdev->globals.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]; ++ pmat->xx *= opdev->globals.zoom[0]; ++ pmat->xy *= opdev->globals.zoom[1]; ++ pmat->yx *= opdev->globals.zoom[0]; ++ pmat->yy *= opdev->globals.zoom[1]; ++ pmat->tx = pmat->tx * opdev->globals.zoom[0] + opdev->globals.shift[0]; ++ pmat->ty = pmat->ty * opdev->globals.zoom[1] + opdev->globals.shift[1]; + } + +- if (pdev->is_open) { ++ if (opdev->is_open) { + /* call ResetCTM */ +- if (apiEntry->opvpResetCTM) { +- apiEntry->opvpResetCTM(printerContext); ++ if (opdev->globals.apiEntry->opvpResetCTM) { ++ opdev->globals.apiEntry->opvpResetCTM(opdev->globals.printerContext); + } else { + /* call SetCTM */ + omat.a = 1; +@@ -2224,8 +2525,8 @@ opvp_get_initial_matrix(gx_device *dev, gs_matrix *pmat) + omat.d = 1; + omat.e = 0; + omat.f = 0; +- if (apiEntry->opvpSetCTM) { +- apiEntry->opvpSetCTM(printerContext, &omat); ++ if (opdev->globals.apiEntry->opvpSetCTM) { ++ opdev->globals.apiEntry->opvpSetCTM(opdev->globals.printerContext, &omat); + } + } + } +@@ -2239,30 +2540,32 @@ opvp_get_initial_matrix(gx_device *dev, gs_matrix *pmat) + static int + opvp_output_page(gx_device *dev, int num_copies, int flush) + { +- gx_device_opvp *pdev = (gx_device_opvp *)dev; ++ gx_device_opvp *opdev = (gx_device_opvp *)dev; + int ecode = 0; + int code = -1; + +- if (inkjet) return gdev_prn_output_page(dev, num_copies, flush); ++ if (opdev->globals.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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + #endif + /* end page */ +- code = opvp_endpage(); ++ code = opvp_endpage(dev); + if (code) ecode = code; + +- pdev->in_page = false; +- beginPage = false; ++ opdev->in_page = false; ++ opdev->globals.beginPage = false; + #ifdef OPVP_IGNORE_BLANK_PAGE + } + #endif + +- if (vector) { +- gdev_vector_reset((gx_device_vector *)pdev); ++ if (opdev->globals.vector) { ++ gdev_vector_reset((gx_device_vector *)dev); + } + + code = gx_finish_output_page(dev, num_copies, flush); +@@ -2289,6 +2592,7 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + int rasterWidth; + bool start_page = false; + bool start_raster = false; ++ gx_device_opvp *opdev = (gx_device_opvp*)pdev; + #if ENABLE_SKIP_RASTER + int i; + byte check; +@@ -2317,8 +2621,8 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + + /* call StartRaster */ + if (!ecode) { +- if (apiEntry->opvpStartRaster) { +- r = apiEntry->opvpStartRaster(printerContext,rasterWidth); ++ if (opdev->globals.apiEntry->opvpStartRaster) { ++ r = opdev->globals.apiEntry->opvpStartRaster(opdev->globals.printerContext,rasterWidth); + } + if (r != OPVP_OK) { + ecode = r; +@@ -2339,7 +2643,7 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + } + #if ENABLE_SKIP_RASTER + /* check support SkipRaster */ +- if (apiEntry->opvpSkipRaster) { ++ if (opdev->globals.apiEntry->opvpSkipRaster) { + /* check all white */ + if (pdev->color_info.depth > 8) { + for (check = 0xff, i = 0; i < raster_size; i++) +@@ -2349,7 +2653,7 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + } + /* if all white call SkipRaster */ + if (check == 0xff) { +- r = apiEntry->opvpSkipRaster(printerContext, 1); ++ r = opdev->globals.apiEntry->opvpSkipRaster(opdev->globals.printerContext, 1); + if (r == OPVP_OK) continue; + } + } else { +@@ -2359,27 +2663,29 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + } + /* if all zero call SkipRaster */ + if (check) { +- r = apiEntry->opvpSkipRaster(printerContext, 1); +- if (r == OPVP_OK) continue; ++ r = opdev->globals.apiEntry->opvpSkipRaster(opdev->globals.printerContext, 1); ++ if (r == OPVP_OK) ++ continue; + } + } + } + #endif + /* call TransferRasterData */ + if (!ecode) { +- if (apiEntry->opvpTransferRasterData) { +- r = apiEntry->opvpTransferRasterData(printerContext, ++ if (opdev->globals.apiEntry->opvpTransferRasterData) { ++ r = opdev->globals.apiEntry->opvpTransferRasterData(opdev->globals.printerContext, + raster_size, + data); + } +- if (r != OPVP_OK) ecode = r; ++ if (r != OPVP_OK) ++ ecode = r; + } + } + + /* call EndRaster */ + if (start_raster) { +- if (apiEntry->opvpEndRaster) { +- r = apiEntry->opvpEndRaster(printerContext); ++ if (opdev->globals.apiEntry->opvpEndRaster) { ++ r = opdev->globals.apiEntry->opvpEndRaster(opdev->globals.printerContext); + } + if (r != OPVP_OK) ecode = r; + start_raster = false; +@@ -2387,7 +2693,7 @@ oprp_print_page(gx_device_printer *pdev, gp_file *prn_stream) + + /* end page */ + if (start_page) { +- code = opvp_endpage(); ++ code = opvp_endpage((gx_device*) pdev); + if (code) ecode = code; + start_page = false; + } +@@ -2411,37 +2717,38 @@ opvp_close(gx_device *dev) + int ecode = 0; + + /* finalize */ +- if (printerContext != -1) { ++ if (pdev->globals.printerContext != -1) { + /* call EndDoc */ +- if (apiEntry->opvpEndDoc) { +- apiEntry->opvpEndDoc(printerContext); ++ if (pdev->globals.apiEntry->opvpEndDoc) { ++ pdev->globals.apiEntry->opvpEndDoc(pdev->globals.printerContext); + } + + /* call EndJob */ +- if (apiEntry->opvpEndJob) { +- apiEntry->opvpEndJob(printerContext); ++ if (pdev->globals.apiEntry->opvpEndJob) { ++ pdev->globals.apiEntry->opvpEndJob(pdev->globals.printerContext); + } + + /* call ClosePrinter */ +- if (apiEntry->opvpClosePrinter) { +- apiEntry->opvpClosePrinter(printerContext); ++ if (pdev->globals.apiEntry->opvpClosePrinter) { ++ pdev->globals.apiEntry->opvpClosePrinter(pdev->globals.printerContext); + } +- printerContext = -1; ++ pdev->globals.printerContext = -1; + } + + /* unload vector driver */ +- if (apiEntry) free(apiEntry); +- apiEntry = NULL; +- opvp_unload_vector_driver(); ++ if (pdev->globals.apiEntry) ++ free(pdev->globals.apiEntry); ++ pdev->globals.apiEntry = NULL; ++ opvp_unload_vector_driver(dev); + +- if (inkjet) { ++ if (pdev->globals.inkjet) { + /* close printer */ + gdev_prn_close(dev); + } else { + /* close output stream */ + gdev_vector_close_file((gx_device_vector *)pdev); + } +- outputFD = -1; ++ pdev->globals.outputFD = -1; + + return ecode; + } +@@ -2455,6 +2762,7 @@ opvp_map_rgb_color(gx_device *dev, + { + opvp_cspace_t cs; + uint c, m, y, k; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + #if !(ENABLE_SIMPLE_MODE) + gx_device_opvp *pdev; +@@ -2467,16 +2775,15 @@ opvp_map_rgb_color(gx_device *dev, + b = prgb[2]; + + #if ENABLE_SIMPLE_MODE +- cs = colorSpace; ++ cs = opdev->globals.colorSpace; + #else + pdev = (gx_device_opvp *)dev; + r = -1; + cs = OPVP_CSPACE_STANDARDRGB; + if (pdev->is_open) { + /* call GetColorSpace */ +- if (apiEntry->opvpGetColorSpace) { +- r = apiEntry->opvpGetColorSpace(printerContext, &cs); +- } ++ ++ r = gsopvpGetColorSpace(dev, opdev->globals.printerContext, &cs); + if (r != OPVP_OK) { + if (pdev->color_info.depth > 32) { + cs = OPVP_CSPACE_STANDARDRGB64; +@@ -2555,15 +2862,14 @@ opvp_map_color_rgb(gx_device *dev, gx_color_index color, + #endif + opvp_cspace_t cs = OPVP_CSPACE_STANDARDRGB; + uint c, m, y, k; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + #if ENABLE_SIMPLE_MODE +- cs = colorSpace; ++ cs = opdev->globals.colorSpace; + #else + /* call GetColorSpace */ + if (pdev->is_open) { +- if (apiEntry->opvpGetColorSpace) { +- r = apiEntry->opvpGetColorSpace(printerContext, &cs); +- } ++ r = gsopvpGetColorSpace(dev, opdev->globals.printerContext, &cs); + if (r != OPVP_OK) { + if (pdev->color_info.depth > 32) { + cs = OPVP_CSPACE_STANDARDRGB64; +@@ -2635,44 +2941,44 @@ opvp_fill_rectangle( + int h, + gx_color_index color) + { +- gx_device_opvp *pdev = (gx_device_opvp *)dev; ++ gx_device_opvp *opdev = (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); ++ if (opdev->globals.vector) { ++ return gdev_vector_fill_rectangle(dev, x, y, w, h, color); + } + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + #if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ +- if (apiEntry->opvpSaveGS) { +- apiEntry->opvpSaveGS(printerContext); ++ if (pdev->globals.apiEntry->opvpSaveGS) { ++ pdev->globals.apiEntry->opvpSaveGS(printerContext); + } + #endif + + /* one-color */ +- opvp_set_brush_color(pdev, color, &brush); ++ opvp_set_brush_color(opdev, color, &brush); + + /* call SetFillColor */ +- if (apiEntry->opvpSetFillColor) { +- apiEntry->opvpSetFillColor(printerContext, &brush); +- } ++ gsopvpSetFillColor(dev, opdev->globals.printerContext, &brush); ++ + + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); +- if (apiEntry->opvpSetCurrentPoint) { +- apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y); ++ if (opdev->globals.apiEntry->opvpSetCurrentPoint) { ++ opdev->globals.apiEntry->opvpSetCurrentPoint(opdev->globals.printerContext,point.x, point.y); + } + + /* draw image */ +- code = opvp_draw_image(pdev, ++ code = opvp_draw_image(opdev, + 1, + 2, 2, + w, h, +@@ -2684,17 +2990,15 @@ opvp_fill_rectangle( + } + + /* restore fill color */ +- if (vectorFillColor) { ++ if (opdev->globals.vectorFillColor) { + /* call SetFillColor */ +- if (apiEntry->opvpSetFillColor) { +- apiEntry->opvpSetFillColor(printerContext,vectorFillColor); +- } ++ gsopvpSetFillColor(dev, opdev->globals.printerContext,opdev->globals.vectorFillColor); + } + + #if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ +- if (apiEntry->opvpRestoreGS) { +- apiEntry->opvpRestoreGS(printerContext); ++ if (pdev->globals.apiEntry->opvpRestoreGS) { ++ pdev->globals.opdev->globals.apiEntry->opvpRestoreGS(printerContext); + } + #endif + +@@ -2718,7 +3022,7 @@ opvp_copy_mono( + gx_color_index zero, + gx_color_index one) + { +- gx_device_opvp *pdev = (gx_device_opvp *)dev; ++ gx_device_opvp *opdev = (gx_device_opvp *)dev; + int code = -1; + int ecode = 0; + opvp_brush_t brush; +@@ -2736,7 +3040,8 @@ opvp_copy_mono( + bool reverse = false; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* data offset */ + if (data_x) { +@@ -2773,8 +3078,8 @@ opvp_copy_mono( + + #if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ +- if (apiEntry->opvpSaveGS) { +- apiEntry->opvpSaveGS(printerContext); ++ if (opdev->globals.apiEntry->opvpSaveGS) { ++ opdev->globals.apiEntry->opvpSaveGS(printerContext); + } + #endif + if (one == gx_no_color_index) { +@@ -2789,25 +3094,22 @@ opvp_copy_mono( + if (zero != gx_no_color_index) { + /* not mask */ + /* Set PaintMode */ +- if (apiEntry->opvpSetPaintMode) { +- apiEntry->opvpSetPaintMode(printerContext,OPVP_PAINTMODE_OPAQUE); ++ if (opdev->globals.apiEntry->opvpSetPaintMode) { ++ opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.printerContext, OPVP_PAINTMODE_OPAQUE); + } + /* zero-color */ +- opvp_set_brush_color(pdev, zero, &brush); ++ opvp_set_brush_color(opdev, zero, &brush); + + /* call SetBgColor */ +- if (apiEntry->opvpSetBgColor) { +- apiEntry->opvpSetBgColor(printerContext, &brush); +- } ++ gsopvpSetBgColor(dev, opdev->globals.printerContext, &brush); ++ + } + + /* one-color */ +- opvp_set_brush_color(pdev, one, &brush); ++ opvp_set_brush_color(opdev, one, &brush); + + /* call SetFillColor */ +- if (apiEntry->opvpSetFillColor) { +- apiEntry->opvpSetFillColor(printerContext, &brush); +- } ++ gsopvpSetFillColor(dev, opdev->globals.printerContext, &brush); + + if (reverse) { + /* 0/1 reverse image */ +@@ -2826,12 +3128,12 @@ opvp_copy_mono( + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); +- if (apiEntry->opvpSetCurrentPoint) { +- apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y); ++ if (opdev->globals.apiEntry->opvpSetCurrentPoint) { ++ opdev->globals.apiEntry->opvpSetCurrentPoint(opdev->globals.printerContext,point.x, point.y); + } + + /* draw image */ +- code = opvp_draw_image(pdev, ++ code = opvp_draw_image(opdev, + 1, + w, h, + w, h, +@@ -2844,23 +3146,21 @@ opvp_copy_mono( + + if (zero != gx_no_color_index) { + /* restore PaintMode */ +- if (apiEntry->opvpSetPaintMode) { +- apiEntry->opvpSetPaintMode(printerContext, ++ if (opdev->globals.apiEntry->opvpSetPaintMode) { ++ opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + } + /* restore fill color */ +- if (vectorFillColor) { ++ if (opdev->globals.vectorFillColor) { + /* call SetFillColor */ +- if (apiEntry->opvpSetFillColor) { +- apiEntry->opvpSetFillColor(printerContext,vectorFillColor); +- } ++ gsopvpSetFillColor(dev, opdev->globals.printerContext,opdev->globals.vectorFillColor); + } + + #if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ +- if (apiEntry->opvpRestoreGS) { +- apiEntry->opvpRestoreGS(printerContext); ++ if (opdev->globals.apiEntry->opvpRestoreGS) { ++ opdev->globals.apiEntry->opvpRestoreGS(opdev->globals.printerContext); + } + #endif + +@@ -2887,7 +3187,7 @@ opvp_copy_color( + int w, + int h) + { +- gx_device_opvp *pdev = (gx_device_opvp *)dev; ++ gx_device_opvp *opdev = (gx_device_opvp *)dev; + int code = -1; + int ecode = 0; + opvp_point_t point; +@@ -2902,11 +3202,12 @@ opvp_copy_color( + int adj_raster = raster; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* data offset */ + if (data_x) { +- depth = pdev->color_info.depth; ++ depth = opdev->color_info.depth; + pixel = (depth + 7) >> 3; + byte_length = pixel * w; + adj_raster = ((byte_length + 3) >> 2) << 2; +@@ -2926,21 +3227,21 @@ opvp_copy_color( + + #if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ +- if (apiEntry->opvpSaveGS) { +- apiEntry->opvpSaveGS(printerContext); ++ if (opdev->globals.apiEntry->opvpSaveGS) { ++ opdev->globals.apiEntry->opvpSaveGS(opdev->globals.printerContext); + } + #endif + + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); +- if (apiEntry->opvpSetCurrentPoint) { +- apiEntry->opvpSetCurrentPoint(printerContext, point.x, point.y); ++ if (opdev->globals.apiEntry->opvpSetCurrentPoint) { ++ opdev->globals.apiEntry->opvpSetCurrentPoint(opdev->globals.printerContext, point.x, point.y); + } + + /* draw image */ +- code = opvp_draw_image(pdev, +- pdev->color_info.depth, ++ code = opvp_draw_image(opdev, ++ opdev->color_info.depth, + w, h, + w, h, + adj_raster, +@@ -2952,8 +3253,8 @@ opvp_copy_color( + + #if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ +- if (apiEntry->opvpRestoreGS) { +- apiEntry->opvpRestoreGS(printerContext); ++ if (opdev->globals.apiEntry->opvpRestoreGS) { ++ opdev->globals.apiEntry->opvpRestoreGS(opdev->globals.printerContext); + } + #endif + +@@ -2969,7 +3270,7 @@ opvp_copy_color( + * get params + */ + static int +-_get_params(gs_param_list *plist) ++_get_params(gx_device* dev, gs_param_list *plist) + { + int code; + int ecode = 0; +@@ -2985,37 +3286,38 @@ _get_params(gs_param_list *plist) + gs_param_string mbps; + gs_param_string zmps; + char buff[OPVP_BUFF_SIZE]; ++ gx_device_opvp* opdev = (gx_device_opvp*)dev; + + /* get params */ + + /* vector driver name */ + pname = "Driver"; +- vdps.data = (byte *)vectorDriver; +- vdps.size = (vectorDriver ? strlen(vectorDriver) + 1 : 0); ++ vdps.data = (byte *)opdev->globals.vectorDriver; ++ vdps.size = (opdev->globals.vectorDriver ? strlen(opdev->globals.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.data = (byte *)opdev->globals.printerModel; ++ pmps.size = (opdev->globals.printerModel ? strlen(opdev->globals.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.data = (byte *)opdev->globals.jobInfo; ++ jips.size = (opdev->globals.jobInfo ? strlen(opdev->globals.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.data = (byte *)opdev->globals.docInfo; ++ dips.size = (opdev->globals.docInfo ? strlen(opdev->globals.docInfo) + 1 : 0); + dips.persistent = false; + code = param_write_string(plist, pname, &dips); + if (code) ecode = code; +@@ -3052,28 +3354,28 @@ _get_params(gs_param_list *plist) + /* margins */ + memset((void*)buff, 0, OPVP_BUFF_SIZE); + pname = "MarginLeft"; +- snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[0]); ++ snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",opdev->globals.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]); ++ snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",opdev->globals.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]); ++ snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",opdev->globals.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]); ++ snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",opdev->globals.margins[1]); + mbps.data = (byte *)buff; + mbps.size = strlen(buff) + 1; + mbps.persistent = false; +@@ -3082,7 +3384,7 @@ _get_params(gs_param_list *plist) + + /* zoom */ + pname = "Zoom"; +- snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",zoom[0]); ++ snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",opdev->globals.zoom[0]); + zmps.data = (byte *)buff; + zmps.size = strlen(buff) + 1; + zmps.persistent = false; +@@ -3105,7 +3407,7 @@ opvp_get_params(gx_device *dev, gs_param_list *plist) + if (code) return code; + + /* get params */ +- return _get_params(plist); ++ return _get_params(dev, plist); + } + + /* +@@ -3121,14 +3423,14 @@ oprp_get_params(gx_device *dev, gs_param_list *plist) + if (code) return code; + + /* get params */ +- return _get_params(plist); ++ return _get_params(dev, plist); + } + + /* + * put params + */ + static int +-_put_params(gs_param_list *plist) ++_put_params(gx_device *dev, gs_param_list *plist) + { + int code; + int ecode = 0; +@@ -3144,6 +3446,7 @@ _put_params(gs_param_list *plist) + gs_param_string mrps; + gs_param_string mbps; + gs_param_string zmps; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + /* vector driver name */ + pname = "Driver"; +@@ -3153,10 +3456,10 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, vdps.size + 1); + memcpy(buff, vdps.data, vdps.size); + buff[vdps.size] = 0; +- opvp_alloc_string(&vectorDriver, buff); ++ opvp_alloc_string(&(opdev->globals.vectorDriver), buff); + break; + case 1: +- /* opvp_alloc_string(&vectorDriver, NULL);*/ ++ /* opvp_alloc_string(&(opdev->globals.vectorDriver), NULL);*/ + break; + default: + ecode = code; +@@ -3171,10 +3474,10 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, pmps.size + 1); + memcpy(buff, pmps.data, pmps.size); + buff[pmps.size] = 0; +- opvp_alloc_string(&printerModel, buff); ++ opvp_alloc_string(&(opdev->globals.printerModel), buff); + break; + case 1: +- /*opvp_alloc_string(&printerModel, NULL);*/ ++ /*opvp_alloc_string(&(opdev->globals.printerModel), NULL);*/ + break; + default: + ecode = code; +@@ -3189,10 +3492,10 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, jips.size + 1); + memcpy(buff, jips.data, jips.size); + buff[jips.size] = 0; +- opvp_alloc_string(&jobInfo, buff); ++ opvp_alloc_string(&(opdev->globals.jobInfo), buff); + break; + case 1: +- /*opvp_alloc_string(&jobInfo, NULL);*/ ++ /*opvp_alloc_string(&(opdev->globals.jobInfo), NULL);*/ + break; + default: + ecode = code; +@@ -3207,10 +3510,10 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, dips.size + 1); + memcpy(buff, dips.data, dips.size); + buff[dips.size] = 0; +- opvp_alloc_string(&docInfo, buff); ++ opvp_alloc_string(&(opdev->globals.docInfo), buff); + break; + case 1: +- /*opvp_alloc_string(&docInfo, NULL);*/ ++ /*opvp_alloc_string(&(opdev->globals.docInfo), NULL);*/ + break; + default: + ecode = code; +@@ -3256,7 +3559,7 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, mlps.size + 1); + memcpy(buff, mlps.data, mlps.size); + buff[mlps.size] = 0; +- margins[0] = atof(buff); ++ opdev->globals.margins[0] = atof(buff); + break; + case 1: + break; +@@ -3271,7 +3574,7 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, mtps.size + 1); + memcpy(buff, mtps.data, mtps.size); + buff[mtps.size] = 0; +- margins[3] = atof(buff); ++ opdev->globals.margins[3] = atof(buff); + break; + case 1: + break; +@@ -3286,7 +3589,7 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, mrps.size + 1); + memcpy(buff, mrps.data, mrps.size); + buff[mrps.size] = 0; +- margins[2] = atof(buff); ++ opdev->globals.margins[2] = atof(buff); + break; + case 1: + break; +@@ -3301,7 +3604,7 @@ _put_params(gs_param_list *plist) + buff = realloc(buff, mbps.size + 1); + memcpy(buff, mbps.data, mbps.size); + buff[mbps.size] = 0; +- margins[1] = atof(buff); ++ opdev->globals.margins[1] = atof(buff); + break; + case 1: + break; +@@ -3319,15 +3622,15 @@ _put_params(gs_param_list *plist) + 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]; ++ opdev->globals.zoom[0] = atof(buff); ++ if (opdev->globals.zoom[0] > 0) { ++ opdev->globals.zoom[1] = opdev->globals.zoom[0]; + } else { +- zoom[0] = zoom[1] = 1; ++ opdev->globals.zoom[0] = opdev->globals.zoom[1] = 1; + } + } else { +- zoom[0] = zoom[1] = 1; +- zoomAuto = true; ++ opdev->globals.zoom[0] = opdev->globals.zoom[1] = 1; ++ opdev->globals.zoomAuto = true; + } + break; + case 1: +@@ -3351,7 +3654,7 @@ opvp_put_params(gx_device *dev, gs_param_list *plist) + int code; + + /* put params */ +- code = _put_params(plist); ++ code = _put_params(dev, plist); + if (code) return code; + + /* put default params */ +@@ -3367,7 +3670,7 @@ oprp_put_params(gx_device *dev, gs_param_list *plist) + int code; + + /* put params */ +- code = _put_params(plist); ++ code = _put_params(dev, plist); + if (code) return code; + + /* put default params */ +@@ -3444,13 +3747,14 @@ opvp_fill_path( + { + bool draw_image = false; + gs_fixed_rect inner, outer; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + /* check if paths are too complex */ + if (!checkPath(ppath) || !checkCPath(pxpath)) { + return gx_default_fill_path(dev, pgs, ppath, params, pdevc, pxpath); + } + /* check clippath support */ +- if (!(apiEntry->opvpSetClipPath)) { ++ if (!(opdev->globals.apiEntry->opvpSetClipPath)) { + /* get clipping box area */ + gx_cpath_inner_box(pxpath,&inner); + gx_cpath_outer_box(pxpath,&outer); +@@ -3462,7 +3766,7 @@ opvp_fill_path( + } + } + +- if (!vector || draw_image) { ++ if (!(opdev->globals.vector) || draw_image) { + return gx_default_fill_path(dev, pgs, ppath, params, pdevc, pxpath); + } + +@@ -3483,6 +3787,7 @@ opvp_stroke_path( + { + bool draw_image = false; + gs_fixed_rect inner, outer; ++ gx_device_opvp *opdev = (gx_device_opvp *) dev; + + /* check if paths are too complex */ + if (!checkPath(ppath) || !checkCPath(pxpath)) { +@@ -3490,7 +3795,7 @@ opvp_stroke_path( + params, pdcolor, pxpath); + } + /* check clippath support */ +- if (!(apiEntry->opvpSetClipPath)) { ++ if (!(opdev->globals.apiEntry->opvpSetClipPath)) { + /* get clipping box area */ + gx_cpath_inner_box(pxpath,&inner); + gx_cpath_outer_box(pxpath,&outer); +@@ -3502,7 +3807,7 @@ opvp_stroke_path( + } + } + +- if (!vector || draw_image) { ++ if (!(opdev->globals.vector) || draw_image) { + return gx_default_stroke_path(dev, pgs, ppath, + params, pdcolor, pxpath); + } +@@ -3530,7 +3835,9 @@ opvp_fill_mask( + gs_logical_operation_t lop, + const gx_clip_path *pcpath) + { +- if (vector) { ++ gx_device_opvp *opdev = (gx_device_opvp*) dev; ++ ++ if (opdev->globals.vector) { + int code; + code = gdev_vector_update_fill_color((gx_device_vector *)dev, NULL, pdcolor); + if (code < 0) return code; +@@ -3574,6 +3881,7 @@ opvp_begin_typed_image( + int p; + float mag[2] = {1, 1}; + const gs_color_space *pcs; ++ gx_device_opvp *opdev = (gx_device_opvp *)dev; + + /* check if paths are too complex */ + if (pic->type->index != 1 || !checkCPath(pcpath)) +@@ -3757,7 +4065,7 @@ opvp_begin_typed_image( + * 3 planes 24 bits color image + * (8 bits per plane) + */ +- if (apiEntry->opvpStartDrawImage) { ++ if (opdev->globals.apiEntry->opvpStartDrawImage) { + draw_image = true; + } + } +@@ -3768,54 +4076,51 @@ opvp_begin_typed_image( + *pinfo = (gx_image_enum_common_t *)vinfo; + + if (!ecode) { ++ opvp_cspace_t ncspace; ++ + if (!pim->ImageMask) { + /* call SetPaintMode */ +- if (apiEntry->opvpSetPaintMode) { +- apiEntry->opvpSetPaintMode(printerContext, ++ if (opdev->globals.apiEntry->opvpSetPaintMode) { ++ opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.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: ++ opdev->globals.savedColorSpace = opdev->globals.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 != opdev->globals.colorSpace) { ++ if (gsopvpSetColorSpace(dev, opdev->globals.printerContext, ncspace) != OPVP_OK) { + r = -1; + goto fallthrough; +- break; +- } +- if (ncspace != colorSpace) { +- if (apiEntry->opvpSetColorSpace(printerContext,ncspace) +- != OPVP_OK) { +- r = -1; +- goto fallthrough; +- } +- colorSpace = ncspace; +- change_cspace = true; + } ++ opdev->globals.colorSpace = ncspace; ++ change_cspace = true; + } + } + } +@@ -3832,8 +4137,8 @@ opvp_begin_typed_image( + ctm.d = mtx.yy; + ctm.e = mtx.tx; + ctm.f = mtx.ty; +- if (apiEntry->opvpSetCTM) { +- r = apiEntry->opvpSetCTM(printerContext, &ctm); ++ if (opdev->globals.apiEntry->opvpSetCTM) { ++ r = opdev->globals.apiEntry->opvpSetCTM(opdev->globals.printerContext, &ctm); + } + else r = -1; + if (r != OPVP_OK) ecode = r; +@@ -3841,38 +4146,33 @@ opvp_begin_typed_image( + } + if (!ecode) { + int dw,dh; ++ opvp_int_t adj_raster; + + /* image size */ + if (mag[0] != 1) { +- dw = floor(vinfo->width * mag[0]+0.5); ++ dw = (int) floor(vinfo->width * mag[0]+0.5); + } else { + dw = vinfo->width; + } + if (mag[1] != 1) { +- dh = floor(vinfo->height * mag[1]+0.5); ++ dh = (int) 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); +- } +- } ++ adj_raster = bits_per_pixel*vinfo->width; ++ adj_raster = ((adj_raster+31) >> 5) << 2; ++ r = gsopvpStartDrawImage(dev, ++ opdev->globals.printerContext, ++ vinfo->width, ++ vinfo->height, ++ adj_raster, ++ pim->ImageMask ? ++ OPVP_IFORMAT_MASK: ++ OPVP_IFORMAT_RAW, ++ dw,dh); ++ if(r != OPVP_OK) { ++ gsopvpEndDrawImage(dev, opdev->globals.printerContext); + } + + /* bugfix for 32bit CMYK image print error */ +@@ -3880,23 +4180,20 @@ fallthrough: + if(r != OPVP_OK) { + if (change_paint_mode) { + /* restore paint mode */ +- if (apiEntry->opvpSetPaintMode) { +- apiEntry->opvpSetPaintMode(printerContext, ++ if (opdev->globals.apiEntry->opvpSetPaintMode) { ++ opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + change_paint_mode = false; + } + if (change_cspace) { + /* restore color space */ +- colorSpace = savedColorSpace; +- if (apiEntry->opvpSetColorSpace) { +- apiEntry->opvpSetColorSpace(printerContext, +- colorSpace); +- } ++ opdev->globals.colorSpace = opdev->globals.savedColorSpace; ++ gsopvpSetColorSpace(dev, opdev->globals.printerContext, opdev->globals.colorSpace); + change_cspace = false; + } +- if(apiEntry->opvpResetCTM) { +- apiEntry->opvpResetCTM(printerContext); /* reset CTM */ ++ if(opdev->globals.apiEntry->opvpResetCTM) { ++ opdev->globals.apiEntry->opvpResetCTM(opdev->globals.printerContext); /* reset CTM */ + } + goto fallback; + } +@@ -3942,6 +4239,7 @@ opvp_image_plane_data( + bbox_image_enum *pbe; + gx_image_enum *tinfo; + const gs_gstate *pgs; ++ gx_device_opvp *opdev = (gx_device_opvp*)(info->dev); + + vinfo = (gdev_vector_image_enum_t *)info; + +@@ -4037,7 +4335,7 @@ opvp_image_plane_data( + 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) { ++ if (opdev->globals.colorSpace == OPVP_CSPACE_DEVICEGRAY) { + /* Convert indexed gray color -> Gray */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes; +@@ -4193,8 +4491,8 @@ opvp_image_plane_data( + /* 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) { ++ if (opdev->globals.colorSpace == OPVP_CSPACE_STANDARDRGB ++ || opdev->globals.colorSpace == OPVP_CSPACE_DEVICERGB) { + /* convert to RGB */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes * 3; +@@ -4206,7 +4504,7 @@ opvp_image_plane_data( + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < data_bytes; j++) { +- unsigned char d = floor( ++ unsigned char d = (unsigned char) floor( + imageDecode[0]*255 + src_ptr[j]* + (imageDecode[1]-imageDecode[0])+0.5); + +@@ -4234,7 +4532,7 @@ opvp_image_plane_data( + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); +- unsigned char d = floor( ++ unsigned char d = (unsigned char) floor( + imageDecode[0]*255 + o* + (imageDecode[1]-imageDecode[0])*255+0.5); + dst_ptr[j*3] = d; /* R */ +@@ -4250,7 +4548,7 @@ opvp_image_plane_data( + vinfo->bits_per_pixel = 24; + } + } +- } else if (colorSpace == OPVP_CSPACE_DEVICEGRAY) { ++ } else if (opdev->globals.colorSpace == OPVP_CSPACE_DEVICEGRAY) { + if (bits_per_pixel == 1) { /* 1bit image */ + dst_bytes = vinfo->width; + dst_length = ((dst_bytes + 3) >> 2) << 2; +@@ -4263,7 +4561,7 @@ opvp_image_plane_data( + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); +- unsigned char d = floor( ++ unsigned char d = (unsigned char) floor( + imageDecode[0]*255 + o* + (imageDecode[1]-imageDecode[0])*255+0.5); + dst_ptr[j] = d; /* R */ +@@ -4299,8 +4597,8 @@ opvp_image_plane_data( + } + + /* call TansferDrawImage */ +- if (apiEntry->opvpTransferDrawImage) { +- apiEntry->opvpTransferDrawImage(printerContext, ++ if (opdev->globals.apiEntry->opvpTransferDrawImage) { ++ opdev->globals.apiEntry->opvpTransferDrawImage(opdev->globals.printerContext, + raster_length * height, (void *)buf); + } + } +@@ -4325,21 +4623,20 @@ opvp_image_end_image(gx_image_enum_common_t *info, bool draw_last) + gx_device_vector *vdev = (gx_device_vector *)dev; + gdev_vector_image_enum_t *vinfo; + opvp_ctm_t ctm; ++ gx_device_opvp *opdev = (gx_device_opvp*)dev; + + vinfo = (gdev_vector_image_enum_t *)info; + + if (begin_image) { + /* call EndDrawImage */ +- if (apiEntry->opvpEndDrawImage) { +- apiEntry->opvpEndDrawImage(printerContext); +- } ++ gsopvpEndDrawImage(dev, opdev->globals.printerContext); + + begin_image = false; + + if (FastImageMode != FastImageNoCTM) { + /* call ResetCTM */ +- if (apiEntry->opvpResetCTM) { +- apiEntry->opvpResetCTM(printerContext); ++ if (opdev->globals.apiEntry->opvpResetCTM) { ++ opdev->globals.apiEntry->opvpResetCTM(opdev->globals.printerContext); + } else { + /* call SetCTM */ + ctm.a = 1; +@@ -4348,25 +4645,24 @@ opvp_image_end_image(gx_image_enum_common_t *info, bool draw_last) + ctm.d = 1; + ctm.e = 0; + ctm.f = 0; +- if (apiEntry->opvpSetCTM) { +- apiEntry->opvpSetCTM(printerContext, &ctm); ++ if (opdev->globals.apiEntry->opvpSetCTM) { ++ opdev->globals.apiEntry->opvpSetCTM(opdev->globals.printerContext, &ctm); + } + } + } + if (change_paint_mode) { + /* restore paint mode */ +- if (apiEntry->opvpSetPaintMode) { +- apiEntry->opvpSetPaintMode(printerContext, ++ if (opdev->globals.apiEntry->opvpSetPaintMode) { ++ opdev->globals.apiEntry->opvpSetPaintMode(opdev->globals.printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + change_paint_mode = false; + } + if (change_cspace) { + /* restore color space */ +- colorSpace = savedColorSpace; +- if (apiEntry->opvpSetColorSpace) { +- apiEntry->opvpSetColorSpace(printerContext, +- colorSpace); ++ opdev->globals.colorSpace = opdev->globals.savedColorSpace; ++ if (gsopvpSetColorSpace(dev, opdev->globals.printerContext, opdev->globals.colorSpace) != OPVP_OK) { ++ return -1; + } + change_cspace = false; + } +@@ -4382,20 +4678,20 @@ opvp_image_end_image(gx_image_enum_common_t *info, bool draw_last) + static int + opvp_beginpage(gx_device_vector *vdev) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + int code = -1; + int ecode = 0; + + #ifdef OPVP_IGNORE_BLANK_PAGE +- if (pdev->in_page) return 0; ++ if (opdev->in_page) return 0; + #endif + /* start page */ +- code = opvp_startpage((gx_device *)pdev); ++ code = opvp_startpage((gx_device *)opdev); + if (code) { + ecode = code; + } else { +- pdev->in_page = true; /* added '05.12.07 */ +- beginPage = true; ++ opdev->in_page = true; /* added '05.12.07 */ ++ opdev->globals.beginPage = true; + } + + return ecode; +@@ -4407,18 +4703,19 @@ opvp_beginpage(gx_device_vector *vdev) + static int + opvp_setlinewidth(gx_device_vector *vdev, double width) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* call SetLineWidth */ + OPVP_F2FIX(width, w); +- if (apiEntry->opvpSetLineWidth) { +- r = apiEntry->opvpSetLineWidth(printerContext, w); ++ if (opdev->globals.apiEntry->opvpSetLineWidth) { ++ r = opdev->globals.apiEntry->opvpSetLineWidth(opdev->globals.printerContext, w); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -4433,13 +4730,14 @@ opvp_setlinewidth(gx_device_vector *vdev, double width) + static int + opvp_setlinecap(gx_device_vector *vdev, gs_line_cap cap) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + switch (cap) { + case gs_cap_butt: +@@ -4458,8 +4756,8 @@ opvp_setlinecap(gx_device_vector *vdev, gs_line_cap cap) + } + + /* call SetLineCap */ +- if (apiEntry->opvpSetLineCap) { +- r = apiEntry->opvpSetLineCap(printerContext, linecap); ++ if (opdev->globals.apiEntry->opvpSetLineCap) { ++ r = opdev->globals.apiEntry->opvpSetLineCap(opdev->globals.printerContext, linecap); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -4474,13 +4772,14 @@ opvp_setlinecap(gx_device_vector *vdev, gs_line_cap cap) + static int + opvp_setlinejoin(gx_device_vector *vdev, gs_line_join join) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + switch (join) { + case gs_join_miter: +@@ -4500,8 +4799,8 @@ opvp_setlinejoin(gx_device_vector *vdev, gs_line_join join) + } + + /* call SetLineJoin */ +- if (apiEntry->opvpSetLineJoin) { +- r = apiEntry->opvpSetLineJoin(printerContext, linejoin); ++ if (opdev->globals.apiEntry->opvpSetLineJoin) { ++ r = opdev->globals.apiEntry->opvpSetLineJoin(opdev->globals.printerContext, linejoin); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -4516,18 +4815,19 @@ opvp_setlinejoin(gx_device_vector *vdev, gs_line_join join) + static int + opvp_setmiterlimit(gx_device_vector *vdev, double limit) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* call SetMiterLimit */ + OPVP_F2FIX(limit, l); +- if (apiEntry->opvpSetMiterLimit) { +- r = apiEntry->opvpSetMiterLimit(printerContext, l); ++ if (opdev->globals.apiEntry->opvpSetMiterLimit) { ++ r = opdev->globals.apiEntry->opvpSetMiterLimit(opdev->globals.printerContext, l); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -4546,7 +4846,7 @@ opvp_setdash( + uint count, + double offset) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_fix_t *p = NULL; +@@ -4554,7 +4854,8 @@ opvp_setdash( + int i; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* pattern */ + if (count) { +@@ -4570,9 +4871,7 @@ opvp_setdash( + + /* call SetLineDash */ + if (!ecode) { +- if (apiEntry->opvpSetLineDash) { +- r = apiEntry->opvpSetLineDash(printerContext, count,p); +- } ++ r = gsopvpSetLineDash((gx_device*) vdev, opdev->globals.printerContext, count,p); + if (r != OPVP_OK) { + ecode = -1; + } +@@ -4581,8 +4880,8 @@ opvp_setdash( + /* call SetLineDashOffset */ + if (!ecode) { + OPVP_F2FIX(offset, o); +- if (apiEntry->opvpSetLineDashOffset) { +- r = apiEntry->opvpSetLineDashOffset(printerContext, o); ++ if (opdev->globals.apiEntry->opvpSetLineDashOffset) { ++ r = opdev->globals.apiEntry->opvpSetLineDashOffset(opdev->globals.printerContext, o); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -4591,8 +4890,8 @@ opvp_setdash( + + /* call SetLineStyle */ + if (!ecode) { +- if (apiEntry->opvpSetLineStyle) { +- r = apiEntry->opvpSetLineStyle(printerContext, ++ if (opdev->globals.apiEntry->opvpSetLineStyle) { ++ r = opdev->globals.apiEntry->opvpSetLineStyle(opdev->globals.printerContext, + (count ? + OPVP_LINESTYLE_DASH : + OPVP_LINESTYLE_SOLID)); +@@ -4613,11 +4912,12 @@ opvp_setdash( + static int + opvp_setflat(gx_device_vector *vdev, double flatness) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + int ecode = 0; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* what to do ? */ + +@@ -4654,26 +4954,26 @@ opvp_setfillcolor( + const gs_gstate *pgs, /* added for gs 8.15 */ + const gx_drawing_color *pdc) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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 (opvp_check_in_page(opdev)) ++ return -1; + + if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck); + + /* color */ +- if (!vectorFillColor) vectorFillColor = &brush; ++ if (!opdev->globals.vectorFillColor) ++ opdev->globals.vectorFillColor = &brush; + color = gx_dc_pure_color(pdc); +- opvp_set_brush_color(pdev, color, vectorFillColor); ++ opvp_set_brush_color(opdev, color, opdev->globals.vectorFillColor); + + /* call SetFillColor */ +- if (apiEntry->opvpSetFillColor) { +- r = apiEntry->opvpSetFillColor(printerContext, vectorFillColor); +- } ++ r = gsopvpSetFillColor((gx_device*) vdev, opdev->globals.printerContext, opdev->globals.vectorFillColor); + if (r != OPVP_OK) { + ecode = -1; + } +@@ -4690,25 +4990,24 @@ opvp_setstrokecolor( + const gs_gstate *pgs, /* added for gs 8.15 */ + const gx_drawing_color *pdc) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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 (opvp_check_in_page(opdev)) ++ 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); ++ opvp_set_brush_color(opdev, color, &brush); + + /* call SetStrokeColor */ +- if (apiEntry->opvpSetStrokeColor) { +- r = apiEntry->opvpSetStrokeColor(printerContext, &brush); +- } ++ r = gsopvpSetStrokeColor((gx_device*) vdev, opdev->globals.printerContext, &brush); + if (r != OPVP_OK) { + ecode = -1; + } +@@ -4728,7 +5027,7 @@ opvp_vector_dopath( + gx_path_type_t type, + const gs_matrix *pmat) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int code = -1; + int ecode = 0; +@@ -4755,7 +5054,8 @@ opvp_vector_dopath( + current.x = current.y = 0; + #endif + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + if (gx_path_is_rectangle(ppath, &rect)) + return (*vdev_proc(vdev, dorect))(vdev, +@@ -4797,9 +5097,9 @@ opvp_vector_dopath( + switch (pop) { + case gs_pe_moveto: + /* call SetCurrentPoint */ +- if (apiEntry->opvpSetCurrentPoint) { +- r = apiEntry->opvpSetCurrentPoint( +- printerContext, ++ if (opdev->globals.apiEntry->opvpSetCurrentPoint) { ++ r = opdev->globals.apiEntry->opvpSetCurrentPoint( ++ opdev->globals.printerContext, + opvp_p[npoints-1].x, + opvp_p[npoints-1].y); + } +@@ -4807,9 +5107,9 @@ opvp_vector_dopath( + break; + case gs_pe_lineto: + /* call LinePath */ +- if (apiEntry->opvpLinePath) { +- r = apiEntry->opvpLinePath( +- printerContext, ++ if (opdev->globals.apiEntry->opvpLinePath) { ++ r = opdev->globals.apiEntry->opvpLinePath( ++ opdev->globals.printerContext, + OPVP_PATHOPEN, + npoints - 1, + &(opvp_p[1])); +@@ -4819,9 +5119,9 @@ opvp_vector_dopath( + case gs_pe_curveto: + /* npoints */ + /* call BezierPath */ +- if (apiEntry->opvpBezierPath) { +- r = apiEntry->opvpBezierPath( +- printerContext, ++ if (opdev->globals.apiEntry->opvpBezierPath) { ++ r = opdev->globals.apiEntry->opvpBezierPath( ++ opdev->globals.printerContext, + npoints - 1, + &(opvp_p[1]) + ); +@@ -4982,7 +5282,7 @@ opvp_vector_dorect( + fixed y1, + gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int code = -1; + int ecode = 0; +@@ -4991,7 +5291,8 @@ opvp_vector_dorect( + _fPoint p; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* begin path */ + code = (*vdev_proc(vdev, beginpath))(vdev, type); +@@ -5010,8 +5311,9 @@ opvp_vector_dorect( + OPVP_F2FIX(p.y, rectangles[0].p1.y); + + /* call RectanglePath */ +- if (apiEntry->opvpRectanglePath) { +- r = apiEntry->opvpRectanglePath(printerContext, ++ if (opdev->globals.apiEntry->opvpRectanglePath) { ++ r = opdev->globals.apiEntry->opvpRectanglePath( ++ opdev->globals.printerContext, + 1, + rectangles); + } +@@ -5038,22 +5340,23 @@ opvp_vector_dorect( + static int + opvp_beginpath(gx_device_vector *vdev, gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* check clip-path */ + if (type & gx_path_type_clip) { +- if (apiEntry->opvpResetClipPath) +- apiEntry->opvpResetClipPath(printerContext); ++ if (opdev->globals.apiEntry->opvpResetClipPath) ++ opdev->globals.apiEntry->opvpResetClipPath(opdev->globals.printerContext); + } + + /* call NewPath */ +- if (apiEntry->opvpNewPath) { +- r = apiEntry->opvpNewPath(printerContext); ++ if (opdev->globals.apiEntry->opvpNewPath) { ++ r = opdev->globals.apiEntry->opvpNewPath(opdev->globals.printerContext); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5074,19 +5377,20 @@ opvp_moveto( + double y1, + gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ 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 (opdev->globals.apiEntry->opvpSetCurrentPoint) { ++ r = opdev->globals.apiEntry->opvpSetCurrentPoint(opdev->globals.printerContext, p.x, p.y); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5107,21 +5411,23 @@ opvp_lineto( + double y1, + gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ 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 (opdev->globals.apiEntry->opvpLinePath) { ++ r = opdev->globals.apiEntry->opvpLinePath( ++ opdev->globals.printerContext, OPVP_PATHOPEN, 1, points); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5146,13 +5452,14 @@ opvp_curveto( + double y3, + gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* points */ + OPVP_F2FIX(x0, points[0].x); +@@ -5165,8 +5472,9 @@ opvp_curveto( + OPVP_F2FIX(y3, points[3].y); + + /* call BezierPath */ +- if (apiEntry->opvpBezierPath) { +- r = apiEntry->opvpBezierPath(printerContext, ++ if (opdev->globals.apiEntry->opvpBezierPath) { ++ r = opdev->globals.apiEntry->opvpBezierPath( ++ opdev->globals.printerContext, + 3, + &(points[1]) + ); +@@ -5190,21 +5498,23 @@ opvp_closepath( + double y_start, + gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (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; ++ if (opvp_check_in_page(opdev)) ++ 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 (opdev->globals.apiEntry->opvpLinePath) { ++ r = opdev->globals.apiEntry->opvpLinePath( ++ opdev->globals.printerContext, OPVP_PATHCLOSE, 1, points); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5219,16 +5529,17 @@ opvp_closepath( + static int + opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + { +- gx_device_opvp *pdev = (gx_device_opvp *)vdev; ++ gx_device_opvp *opdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + + /* check page-in */ +- if (opvp_check_in_page(pdev)) return -1; ++ if (opvp_check_in_page(opdev)) ++ return -1; + + /* call EndPath */ +- if (apiEntry->opvpEndPath) { +- r = apiEntry->opvpEndPath(printerContext); ++ if (opdev->globals.apiEntry->opvpEndPath) { ++ r = opdev->globals.apiEntry->opvpEndPath(opdev->globals.printerContext); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5238,9 +5549,9 @@ opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + /* fill mode */ + if (type & gx_path_type_even_odd) { + /* call SetFillMode */ +- if (apiEntry->opvpSetFillMode) { +- r = apiEntry->opvpSetFillMode( +- printerContext, ++ if (opdev->globals.apiEntry->opvpSetFillMode) { ++ r = opdev->globals.apiEntry->opvpSetFillMode( ++ opdev->globals.printerContext, + OPVP_FILLMODE_EVENODD + ); + } +@@ -5249,9 +5560,9 @@ opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + } + } else { + /* call SetFillMode */ +- if (apiEntry->opvpSetFillMode) { +- r = apiEntry->opvpSetFillMode( +- printerContext, ++ if (opdev->globals.apiEntry->opvpSetFillMode) { ++ r = opdev->globals.apiEntry->opvpSetFillMode( ++ opdev->globals.printerContext, + OPVP_FILLMODE_WINDING + ); + } +@@ -5262,16 +5573,16 @@ opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + + if (type & gx_path_type_stroke) { + /* call StrokeFillPath */ +- if (apiEntry->opvpStrokeFillPath) { +- r = apiEntry->opvpStrokeFillPath(printerContext); ++ if (opdev->globals.apiEntry->opvpStrokeFillPath) { ++ r = opdev->globals.apiEntry->opvpStrokeFillPath(opdev->globals.printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + } else { + /* call FillPath */ +- if (apiEntry->opvpFillPath) { +- r = apiEntry->opvpFillPath(printerContext); ++ if (opdev->globals.apiEntry->opvpFillPath) { ++ r = opdev->globals.apiEntry->opvpFillPath(opdev->globals.printerContext); + } + if (r != OPVP_OK) { + ecode = -1; +@@ -5279,9 +5590,9 @@ opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + } + } else if (type & gx_path_type_clip) { + /* call SetClipPath */ +- if (apiEntry->opvpSetClipPath) { +- r = apiEntry->opvpSetClipPath( +- printerContext, ++ if (opdev->globals.apiEntry->opvpSetClipPath) { ++ r = opdev->globals.apiEntry->opvpSetClipPath( ++ opdev->globals.printerContext, + (type & gx_path_type_even_odd + ? OPVP_CLIPRULE_EVENODD + : OPVP_CLIPRULE_WINDING)); +@@ -5291,8 +5602,8 @@ opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) + } + } else if (type & gx_path_type_stroke) { + /* call StrokePath */ +- if (apiEntry->opvpStrokePath) { +- r = apiEntry->opvpStrokePath(printerContext); ++ if (opdev->globals.apiEntry->opvpStrokePath) { ++ r = opdev->globals.apiEntry->opvpStrokePath(opdev->globals.printerContext); + } + if (r != OPVP_OK) { + ecode = -1; +diff --git a/contrib/opvp/opvp.h b/contrib/opvp/opvp.h +index 426e8cf..db09046 100644 +--- a/contrib/opvp/opvp.h ++++ b/contrib/opvp/opvp.h +@@ -160,7 +160,7 @@ typedef struct _opvp_brushdata { + #elif defined(__HP_cc) + opvp_byte_t data[1]; + #else +- opvp_byte_t data[]; ++ opvp_byte_t data[1]; + #endif + + } opvp_brushdata_t; +@@ -222,8 +222,8 @@ typedef struct _opvp_api_procs { + 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 (*opvpQueryDeviceCapability)(opvp_dc_t, opvp_queryinfoflags_t,opvp_int_t*,opvp_byte_t*); ++ opvp_result_t (*opvpQueryDeviceInfo)(opvp_dc_t, opvp_queryinfoflags_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*); +@@ -287,8 +287,7 @@ typedef struct _opvp_api_procs { + } opvp_api_procs_t; + + /* Function prototype */ +-opvp_dc_t opvpOpenPrinter( +- opvp_int_t outputFD, ++extern opvp_dc_t opvpOpenPrinter(opvp_int_t outputFD, + const opvp_char_t *printerModel, + const opvp_int_t apiVersion[2], + opvp_api_procs_t **apiProcs); +diff --git a/contrib/opvp/opvp_0_2_0.h b/contrib/opvp/opvp_0_2_0.h +index 6030971..8518b7e 100644 +--- a/contrib/opvp/opvp_0_2_0.h ++++ b/contrib/opvp/opvp_0_2_0.h +@@ -210,7 +210,7 @@ typedef struct _OPVP_CTM { + typedef struct _OPVP_api_procs { + int (*OpenPrinter)(int,char *,int *,struct _OPVP_api_procs **); + int (*ClosePrinter)(int); +- int (*StartJob)(int,char *); ++ int (*StartJob)(int, char *); + int (*EndJob)(int); + int (*StartDoc)(int,char *); + int (*EndDoc)(int); +@@ -238,7 +238,7 @@ typedef struct _OPVP_api_procs { + int (*GetAlphaConstant)(int,float *); + int (*SetLineWidth)(int,OPVP_Fix); + int (*GetLineWidth)(int,OPVP_Fix *); +- int (*SetLineDash)(int,OPVP_Fix *,int); ++ int (*SetLineDash)(int, int, OPVP_Fix *); + int (*GetLineDash)(int,OPVP_Fix *,int *); + int (*SetLineDashOffset)(int,OPVP_Fix); + int (*GetLineDashOffset)(int,OPVP_Fix *); +diff --git a/contrib/opvp/opvpharness.c b/contrib/opvp/opvpharness.c +new file mode 100644 +index 0000000..95919f4 +--- /dev/null ++++ b/contrib/opvp/opvpharness.c +@@ -0,0 +1,947 @@ ++/* Test harness for checking results after ++ removal of globals in opvp device. Note, ++ 0.2 API not tested. Assumption is OpenPrinter ++ is the first method called and ClosePrinter ++ will be the final method called. If not, ++ there will be problems. */ ++ ++#include "opvp.h" ++#include ++#include ++#include ++ ++/* Yes globals, but here we don't care */ ++FILE *pFile = NULL; ++ ++/* Graphic state members of API that are set and get. */ ++typedef struct opvp_gstate_s { ++ opvp_ctm_t ctm; ++ opvp_cspace_t colorspace; ++ opvp_fillmode_t fill_mode; ++ opvp_float_t alpha; ++ opvp_fix_t line_width; ++ opvp_int_t line_dash_n; ++ opvp_fix_t *line_dash_array; ++ opvp_fix_t dash_offset; ++ opvp_linestyle_t line_style; ++ opvp_linecap_t line_cap; ++ opvp_linejoin_t line_join; ++ opvp_fix_t miter_limit; ++ opvp_paintmode_t paintmode; ++} opvp_gstate_t; ++ ++opvp_gstate_t opv_gstate; ++ ++static opvp_result_t ++opvpClosePrinter(opvp_dc_t printerContext) ++{ ++ fputs("opvpClosePrinter\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fclose(pFile); ++ ++ if (opv_gstate.line_dash_array != NULL) ++ free(opv_gstate.line_dash_array); ++ ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartJob(opvp_dc_t printerContext, const opvp_char_t *job_info) ++{ ++ fputs("opvpStartJob\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tjob_info = %s\n", job_info); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndJob(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndJob\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpAbortJob(opvp_dc_t printerContext) ++{ ++ fputs("opvpAbortJob\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartDoc(opvp_dc_t printerContext, const opvp_char_t *docinfo) ++{ ++ fputs("opvpStartDoc\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tjob_info = %s\n", docinfo); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndDoc(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndDoc\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartPage(opvp_dc_t printerContext, const opvp_char_t *pageinfo) ++{ ++ fputs("opvpStartPage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tjob_info = %s\n", pageinfo); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndPage(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndPage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* Not used */ ++static opvp_result_t ++opvpQueryDeviceCapability(opvp_dc_t printerContext, opvp_flag_t flag, opvp_int_t *a, opvp_byte_t *b) ++{ ++ fputs("opvpQueryDeviceCapability\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* Not used */ ++static opvp_result_t ++opvpQueryDeviceInfo(opvp_dc_t printerContext, opvp_flag_t flag, opvp_int_t *a, opvp_char_t *b) ++{ ++ fputs("opvpQueryDeviceInfo\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpResetCTM(opvp_dc_t printerContext) ++{ ++ fputs("opvpResetCTM\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ opv_gstate.ctm.a = 1.0; ++ opv_gstate.ctm.b = 0.0; ++ opv_gstate.ctm.c = 0.0; ++ opv_gstate.ctm.d = 1.0; ++ opv_gstate.ctm.e = 0.0; ++ opv_gstate.ctm.f = 0.0; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetCTM(opvp_dc_t printerContext, const opvp_ctm_t *pctm) ++{ ++ fputs("opvpSetCTM\n", pFile); ++ opv_gstate.ctm = *pctm; ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tctm.a = %f\n", pctm->a); ++ fprintf(pFile, "\tctm.b = %f\n", pctm->b); ++ fprintf(pFile, "\tctm.c = %f\n", pctm->c); ++ fprintf(pFile, "\tctm.d = %f\n", pctm->d); ++ fprintf(pFile, "\tctm.e = %f\n", pctm->e); ++ fprintf(pFile, "\tctm.f = %f\n", pctm->f); ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetCTM(opvp_dc_t printerContext, opvp_ctm_t *pctm) ++{ ++ fputs("opvpGetCTM\n", pFile); ++ *pctm = opv_gstate.ctm; ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpInitGS(opvp_dc_t printerContext) ++{ ++ fputs("opvpInitGS\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpSaveGS(opvp_dc_t printerContext) ++{ ++ fputs("opvpSaveGS\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpRestoreGS(opvp_dc_t printerContext) ++{ ++ fputs("opvpRestoreGS\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpQueryColorSpace(opvp_dc_t printerContext, opvp_int_t *n, opvp_cspace_t *colorspace) ++{ ++ fputs("opvpQueryColorSpace\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *n = 0; ++ *colorspace = opv_gstate.colorspace; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetColorSpace(opvp_dc_t printerContext, opvp_cspace_t colorspace) ++{ ++ fputs("opvpSetColorSpace\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tcolorspace = %d\n", colorspace); ++ opv_gstate.colorspace = colorspace; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetColorSpace(opvp_dc_t printerContext, opvp_cspace_t *colorspace) ++{ ++ fputs("opvpGetColorSpace\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *colorspace = opv_gstate.colorspace; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetFillMode(opvp_dc_t printerContext, opvp_fillmode_t fillmode) ++{ ++ fputs("opvpSetFillMode\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tfillmode = %d\n", fillmode); ++ opv_gstate.fill_mode = fillmode; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetFillMode(opvp_dc_t printerContext, opvp_fillmode_t *fillmode) ++{ ++ fputs("opvpGetFillMode\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *fillmode = opv_gstate.fill_mode; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetAlphaConstant(opvp_dc_t printerContext, opvp_float_t alpha) ++{ ++ fputs("opvpSetAlphaConstant\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\talpha = %f\n", alpha); ++ opv_gstate.alpha = alpha; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetAlphaConstant(opvp_dc_t printerContext, opvp_float_t *alpha) ++{ ++ fputs("opvpGetAlphaConstant\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *alpha = opv_gstate.alpha; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineWidth(opvp_dc_t printerContext, opvp_fix_t width) ++{ ++ fputs("opvpSetLineWidth\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\twidth = %d\n", width); ++ opv_gstate.line_width = width; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineWidth(opvp_dc_t printerContext, opvp_fix_t *width) ++{ ++ fputs("opvpGetLineWidth\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *width = opv_gstate.line_width; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineDash(opvp_dc_t printerContext, opvp_int_t n, const opvp_fix_t *dash) ++{ ++ int k; ++ ++ fputs("opvpSetLineDash\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tn = %d\n", n); ++ opv_gstate.line_dash_n = n; ++ ++ if (opv_gstate.line_dash_array != NULL) ++ free(opv_gstate.line_dash_array); ++ ++ opv_gstate.line_dash_array = (opvp_fix_t*) malloc(n * sizeof(opvp_fix_t)); ++ if (opv_gstate.line_dash_array == NULL) { ++ fprintf(pFile,"\t Error in dash array allocation. Exiting."); ++ fclose(pFile); ++ exit(-1); ++ } ++ ++ for (k = 0; k < n; k++) { ++ opv_gstate.line_dash_array[k] = dash[k]; ++ fprintf(pFile, "\tdash[%d] = %d\n", k, dash[k]); ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineDash(opvp_dc_t printerContext, opvp_int_t *n, opvp_fix_t *dash) ++{ ++ fputs("opvpGetLineDash\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ ++ *n = opv_gstate.line_dash_n; ++ dash = opv_gstate.line_dash_array; ++ ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineDashOffset(opvp_dc_t printerContext, opvp_fix_t offset) ++{ ++ fputs("opvpSetLineDashOffset\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\toffset = %d\n", offset); ++ opv_gstate.dash_offset = offset; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineDashOffset(opvp_dc_t printerContext, opvp_fix_t *offset) ++{ ++ fputs("opvpGetLineDashOffset\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *offset = opv_gstate.dash_offset; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineStyle(opvp_dc_t printerContext, opvp_linestyle_t style) ++{ ++ fputs("opvpSetLineStyle\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tstyle = %d\n", style); ++ opv_gstate.line_style = style; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineStyle(opvp_dc_t printerContext, opvp_linestyle_t *style) ++{ ++ fputs("opvpGetLineStyle\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *style = opv_gstate.line_style; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineCap(opvp_dc_t printerContext, opvp_linecap_t cap) ++{ ++ fputs("opvpSetLineCap\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tcap = %d\n", cap); ++ opv_gstate.line_cap = cap; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineCap(opvp_dc_t printerContext, opvp_linecap_t *cap) ++{ ++ fputs("opvpGetLineCap\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *cap = opv_gstate.line_cap; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetLineJoin(opvp_dc_t printerContext, opvp_linejoin_t join) ++{ ++ fputs("opvpSetLineJoin\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tjoin = %d\n", join); ++ opv_gstate.line_join = join; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetLineJoin(opvp_dc_t printerContext, opvp_linejoin_t *join) ++{ ++ fputs("opvpGetLineJoin\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *join = opv_gstate.line_join; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetMiterLimit(opvp_dc_t printerContext, opvp_fix_t miter) ++{ ++ fputs("opvpSetMiterLimit\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tmiter = %d\n", miter); ++ opv_gstate.miter_limit = miter; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetMiterLimit(opvp_dc_t printerContext, opvp_fix_t *miter) ++{ ++ fputs("opvpGetMiterLimit\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *miter = opv_gstate.miter_limit; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetPaintMode(opvp_dc_t printerContext, opvp_paintmode_t paintmode) ++{ ++ fputs("opvpSetPaintMode\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tpaintmode = %d\n", paintmode); ++ opv_gstate.paintmode = paintmode; ++ return 0; ++} ++ ++static opvp_result_t ++opvpGetPaintMode(opvp_dc_t printerContext, opvp_paintmode_t *paintmode) ++{ ++ fputs("opvpGetPaintMode\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ *paintmode = opv_gstate.paintmode; ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetStrokeColor(opvp_dc_t printerContext, const opvp_brush_t *strokecolor) ++{ ++ int k; ++ ++ fputs("opvpSetStrokeColor\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ if (strokecolor == NULL) { ++ fprintf(pFile, "\tstrokecolor is NULL\n"); ++ } else { ++ fprintf(pFile, "\tstrokecolor.colorSpace = %d\n", strokecolor->colorSpace); ++ ++ for (k = 0; k < 4; k++) { ++ fprintf(pFile, "\tstrokecolor.color[%d] = %d\n", k, strokecolor->color[k]); ++ } ++ ++ fprintf(pFile, "\tstrokecolor.xorg = %d\n", strokecolor->xorg); ++ fprintf(pFile, "\tstrokecolor.yorg = %d\n", strokecolor->yorg); ++ ++ if (strokecolor->pbrush == NULL) { ++ fprintf(pFile, "\tstrokecolor.pbrush is NULL\n"); ++ } else { ++ fprintf(pFile, "\tstrokecolor.pbrush.type = %d\n", strokecolor->pbrush->type); ++ fprintf(pFile, "\tstrokecolor.pbrush.width = %d\n", strokecolor->pbrush->width); ++ fprintf(pFile, "\tstrokecolor.pbrush.height = %d\n", strokecolor->pbrush->height); ++ fprintf(pFile, "\tstrokecolor.pbrush.pitch = %d\n", strokecolor->pbrush->pitch); ++ } ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetFillColor(opvp_dc_t printerContext, const opvp_brush_t *fillcolor) ++{ ++ int k; ++ ++ fputs("opvpSetFillColor\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ if (fillcolor == NULL) { ++ fprintf(pFile, "\tfillcolor is NULL\n"); ++ } else { ++ fprintf(pFile, "\tfillcolor.colorSpace = %d\n", fillcolor->colorSpace); ++ ++ for (k = 0; k < 4; k++) { ++ fprintf(pFile, "\tfillcolor.color[%d] = %d\n", k, fillcolor->color[k]); ++ } ++ ++ fprintf(pFile, "\tfillcolor.xorg = %d\n", fillcolor->xorg); ++ fprintf(pFile, "\tfillcolor.yorg = %d\n", fillcolor->yorg); ++ ++ if (fillcolor->pbrush == NULL) { ++ fprintf(pFile, "\tfillcolor.pbrush is NULL\n"); ++ } else { ++ fprintf(pFile, "\tfillcolor.pbrush.type = %d\n", fillcolor->pbrush->type); ++ fprintf(pFile, "\tfillcolor.pbrush.width = %d\n", fillcolor->pbrush->width); ++ fprintf(pFile, "\tfillcolor.pbrush.height = %d\n", fillcolor->pbrush->height); ++ fprintf(pFile, "\tfillcolor.pbrush.pitch = %d\n", fillcolor->pbrush->pitch); ++ } ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetBgColor(opvp_dc_t printerContext, const opvp_brush_t *bgcolor) ++{ ++ int k; ++ ++ fputs("opvpSetBgColor\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ if (bgcolor == NULL) { ++ fprintf(pFile, "\tfillcbgcolorolor is NULL\n"); ++ } else { ++ fprintf(pFile, "\tbgcolor.colorSpace = %d\n", bgcolor->colorSpace); ++ ++ for (k = 0; k < 4; k++) { ++ fprintf(pFile, "\tbgcolor.color[%d] = %d\n", k, bgcolor->color[k]); ++ } ++ ++ fprintf(pFile, "\tbgcolor.xorg = %d\n", bgcolor->xorg); ++ fprintf(pFile, "\tbgcolor.yorg = %d\n", bgcolor->yorg); ++ ++ if (bgcolor->pbrush == NULL) { ++ fprintf(pFile, "\tbgcolor.pbrush is NULL\n"); ++ } else { ++ fprintf(pFile, "\tbgcolor.pbrush.type = %d\n", bgcolor->pbrush->type); ++ fprintf(pFile, "\tbgcolor.pbrush.width = %d\n", bgcolor->pbrush->width); ++ fprintf(pFile, "\tbgcolor.pbrush.height = %d\n", bgcolor->pbrush->height); ++ fprintf(pFile, "\tbgcolor.pbrush.pitch = %d\n", bgcolor->pbrush->pitch); ++ } ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpNewPath(opvp_dc_t printerContext) ++{ ++ fputs("opvpNewPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndPath(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStrokePath(opvp_dc_t printerContext) ++{ ++ fputs("opvpStrokePath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpFillPath(opvp_dc_t printerContext) ++{ ++ fputs("opvpFillPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStrokeFillPath(opvp_dc_t printerContext) ++{ ++ fputs("opvpStrokeFillPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetClipPath(opvp_dc_t printerContext, opvp_cliprule_t cliprule) ++{ ++ fputs("opvpSetClipPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tcliprule = %d\n", cliprule); ++ return 0; ++} ++ ++static opvp_result_t ++opvpResetClipPath(opvp_dc_t printerContext) ++{ ++ fputs("opvpResetClipPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpSetCurrentPoint(opvp_dc_t printerContext, opvp_fix_t pointx, opvp_fix_t pointy) ++{ ++ fputs("opvpSetCurrentPoint\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tpointx = %d\n", pointx); ++ fprintf(pFile, "\tpointy = %d\n", pointy); ++ return 0; ++} ++ ++static opvp_result_t ++opvpLinePath(opvp_dc_t printerContext, opvp_pathmode_t pathmode, opvp_int_t npoints, const opvp_point_t *points) ++{ ++ int k; ++ ++ fputs("opvpLinePath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tpathmode = %d\n", pathmode); ++ fprintf(pFile, "\tnpoints = %d\n", npoints); ++ ++ for (k = 0; k < npoints; k++) { ++ fprintf(pFile, "\tpoints[%d].x = %d\n", k, points[k].x); ++ fprintf(pFile, "\tpoints[%d].y = %d\n", k, points[k].y); ++ } ++ return 0; ++} ++ ++/* Not used */ ++static opvp_result_t ++opvpPolygonPath(opvp_dc_t printerContext, opvp_int_t n, const opvp_int_t *m, const opvp_point_t *p) ++{ ++ fputs("opvpPolygonPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpRectanglePath(opvp_dc_t printerContext, opvp_int_t n, const opvp_rectangle_t *rects) ++{ ++ int k; ++ ++ fputs("opvpRectanglePath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tn = %d\n", n); ++ ++ for (k = 0; k < n; k++) { ++ fprintf(pFile, "\trects[%d].p0.x = %d\n", k, rects[k].p0.x); ++ fprintf(pFile, "\trects[%d].p0.y = %d\n", k, rects[k].p0.y); ++ fprintf(pFile, "\trects[%d].p1.x = %d\n", k, rects[k].p1.x); ++ fprintf(pFile, "\trects[%d].p1.y = %d\n", k, rects[k].p1.y); ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpRoundRectanglePath(opvp_dc_t printerContext, opvp_int_t n, const opvp_roundrectangle_t *rects) ++{ ++ int k; ++ ++ fputs("opvpRoundRectanglePath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tn = %d\n", n); ++ ++ for (k = 0; k < n; k++) { ++ fprintf(pFile, "\trects[%d].p0.x = %d\n", k, rects[k].p0.x); ++ fprintf(pFile, "\trects[%d].p0.y = %d\n", k, rects[k].p0.y); ++ fprintf(pFile, "\trects[%d].p1.x = %d\n", k, rects[k].p1.x); ++ fprintf(pFile, "\trects[%d].p1.y = %d\n", k, rects[k].p1.y); ++ fprintf(pFile, "\trects[%d].xellipse = %d\n", k, rects[k].xellipse); ++ fprintf(pFile, "\trects[%d].yellipse = %d\n", k, rects[k].yellipse); ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpBezierPath(opvp_dc_t printerContext, opvp_int_t n, const opvp_point_t *points) ++{ ++ int k; ++ ++ fputs("opvpBezierPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tn = %d\n", n); ++ ++ for (k = 0; k < n; k++) { ++ fprintf(pFile, "\tpoints[%d].x = %d\n", k, points[k].x); ++ fprintf(pFile, "\trects[%d].y = %d\n", k, points[k].y); ++ ++ } ++ return 0; ++} ++ ++/* Not used */ ++static opvp_result_t ++opvpArcPath(opvp_dc_t printerContext, opvp_arcmode_t mode, opvp_arcdir_t dir, ++ opvp_fix_t a, opvp_fix_t b, opvp_fix_t c, opvp_fix_t d, opvp_fix_t e, opvp_fix_t f, ++ opvp_fix_t g, opvp_fix_t h) ++{ ++ fputs("opvpArcPath\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpDrawImage(opvp_dc_t printerContext, opvp_int_t sw, opvp_int_t sh, opvp_int_t raster, ++ opvp_imageformat_t format, opvp_int_t dw, opvp_int_t dh, const void *data) ++{ ++ int k; ++ unsigned char *data_char = (unsigned char*) data; ++ ++ fputs("opvpDrawImage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tsw = %d\n", sw); ++ fprintf(pFile, "\tsh = %d\n", sh); ++ fprintf(pFile, "\traster = %d\n", raster); ++ fprintf(pFile, "\tformat = %d\n", format); ++ fprintf(pFile, "\tdw = %d\n", dw); ++ fprintf(pFile, "\tdh = %d\n", dh); ++ ++ /* No idea how big data is here... Try sw, as byte? */ ++ for (k = 0; k < sw; k++) { ++ fprintf(pFile, "\tdata[%d] = %d\n", k, data_char[k]); ++ } ++ ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartDrawImage(opvp_dc_t printerContext, opvp_int_t sw, opvp_int_t sh, opvp_int_t raster, ++ opvp_imageformat_t format, opvp_int_t dw, opvp_int_t dh) ++{ ++ fputs("opvpStartDrawImage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tsw = %d\n", sw); ++ fprintf(pFile, "\tsh = %d\n", sh); ++ fprintf(pFile, "\traster = %d\n", raster); ++ fprintf(pFile, "\tformat = %d\n", format); ++ fprintf(pFile, "\tdw = %d\n", dw); ++ fprintf(pFile, "\tdh = %d\n", dh); ++ return 0; ++} ++ ++static opvp_result_t ++opvpTransferDrawImage(opvp_dc_t printerContext, opvp_int_t count, const void *data) ++{ ++ int k; ++ unsigned char *data_char = (unsigned char*) data; ++ ++ fputs("opvpTransferDrawImage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\tcount = %d\n", count); ++ ++ for (k = 0; k < count; k++) { ++ fprintf(pFile, "\tdata[%d] = %d\n", k, data_char[k]); ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndDrawImage(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndDrawImage\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* not used */ ++static opvp_result_t ++opvpStartScanline(opvp_dc_t printerContext, opvp_int_t a) ++{ ++ fputs("opvpStartScanline\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* not used */ ++static opvp_result_t ++opvpScanline(opvp_dc_t printerContext, opvp_int_t a, const opvp_int_t *b) ++{ ++ fputs("opvpScanline\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* not used */ ++static opvp_result_t ++opvpEndScanline(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndScanline\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartRaster(opvp_dc_t printerContext, opvp_int_t width) ++{ ++ fputs("opvpStartRaster\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\twidth = %d\n", width); ++ return 0; ++} ++ ++static opvp_result_t ++opvpTransferRasterData(opvp_dc_t printerContext, opvp_int_t raster_size, const opvp_byte_t *data) ++{ ++ int k; ++ ++ fputs("opvpTransferRasterData\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\traster_size = %d\n", raster_size); ++ ++ for (k = 0; k < raster_size; k++) { ++ fprintf(pFile, "\tdata[%d] = %d\n", k, data[k]); ++ } ++ return 0; ++} ++ ++static opvp_result_t ++opvpSkipRaster(opvp_dc_t printerContext, opvp_int_t a) ++{ ++ fputs("opvpSkipRaster\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ fprintf(pFile, "\ta = %d\n", a); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndRaster(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndRaster\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpStartStream(opvp_dc_t printerContext) ++{ ++ fputs("opvpStartStream\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++/* Not used */ ++static opvp_result_t ++opvpTransferStreamData(opvp_dc_t printerContext, opvp_int_t a, const void *b) ++{ ++ fputs("opvpTransferStreamData\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++static opvp_result_t ++opvpEndStream(opvp_dc_t printerContext) ++{ ++ fputs("opvpEndStream\n", pFile); ++ fprintf(pFile, "\tContext = %d\n", printerContext); ++ return 0; ++} ++ ++opvp_int_t opvpErrorNo; ++ ++opvp_dc_t ++opvpOpenPrinter(opvp_int_t outputFD, const opvp_char_t *printerModel, const opvp_int_t apiVersion[2], ++ opvp_api_procs_t **apiProcs) ++{ ++ static opvp_api_procs_t procs; ++ opvp_fix_t fixed_value; ++ ++ procs.opvpEndStream = opvpEndStream; ++ procs.opvpClosePrinter = opvpClosePrinter; ++ procs.opvpStartJob = opvpStartJob; ++ procs.opvpEndJob = opvpEndJob; ++ procs.opvpAbortJob = opvpAbortJob; ++ procs.opvpStartDoc = opvpStartDoc; ++ procs.opvpEndDoc = opvpEndDoc; ++ procs.opvpStartPage = opvpStartPage; ++ procs.opvpEndPage = opvpEndPage; ++ procs.opvpQueryDeviceCapability = opvpQueryDeviceCapability; ++ procs.opvpQueryDeviceInfo = opvpQueryDeviceInfo; ++ procs.opvpResetCTM = opvpResetCTM; ++ procs.opvpSetCTM = opvpSetCTM; ++ procs.opvpGetCTM = opvpGetCTM; ++ procs.opvpInitGS = opvpInitGS; ++ procs.opvpSaveGS = opvpSaveGS; ++ procs.opvpRestoreGS = opvpRestoreGS; ++ procs.opvpQueryColorSpace = opvpQueryColorSpace; ++ procs.opvpSetColorSpace = opvpSetColorSpace; ++ procs.opvpGetColorSpace = opvpGetColorSpace; ++ procs.opvpSetFillMode = opvpSetFillMode; ++ procs.opvpGetFillMode = opvpGetFillMode; ++ procs.opvpSetAlphaConstant = opvpSetAlphaConstant; ++ procs.opvpGetAlphaConstant = opvpGetAlphaConstant; ++ procs.opvpSetLineWidth = opvpSetLineWidth; ++ procs.opvpGetLineWidth = opvpGetLineWidth; ++ procs.opvpSetLineDash = opvpSetLineDash; ++ procs.opvpSetLineDash = opvpSetLineDash; ++ procs.opvpGetLineDash = opvpGetLineDash; ++ procs.opvpSetLineDashOffset = opvpSetLineDashOffset; ++ procs.opvpGetLineDashOffset = opvpGetLineDashOffset; ++ procs.opvpSetLineStyle = opvpSetLineStyle; ++ procs.opvpGetLineStyle = opvpGetLineStyle; ++ procs.opvpSetLineCap = opvpSetLineCap; ++ procs.opvpGetLineCap = opvpGetLineCap; ++ procs.opvpSetLineJoin = opvpSetLineJoin; ++ procs.opvpGetLineJoin = opvpGetLineJoin; ++ procs.opvpSetMiterLimit = opvpSetMiterLimit; ++ procs.opvpGetMiterLimit = opvpGetMiterLimit; ++ procs.opvpSetPaintMode = opvpSetPaintMode; ++ procs.opvpGetPaintMode = opvpGetPaintMode; ++ procs.opvpSetStrokeColor = opvpSetStrokeColor; ++ procs.opvpSetFillColor = opvpSetFillColor; ++ procs.opvpSetBgColor = opvpSetBgColor; ++ procs.opvpNewPath = opvpNewPath; ++ procs.opvpEndPath = opvpEndPath; ++ procs.opvpStrokePath = opvpStrokePath; ++ procs.opvpFillPath = opvpFillPath; ++ procs.opvpStrokeFillPath = opvpStrokeFillPath; ++ procs.opvpSetClipPath = opvpSetClipPath; ++ procs.opvpResetClipPath = opvpResetClipPath; ++ procs.opvpSetCurrentPoint = opvpSetCurrentPoint; ++ procs.opvpLinePath = opvpLinePath; ++ procs.opvpPolygonPath = opvpPolygonPath; ++ procs.opvpRectanglePath = opvpRectanglePath; ++ procs.opvpRoundRectanglePath = opvpRoundRectanglePath; ++ procs.opvpBezierPath = opvpBezierPath; ++ procs.opvpArcPath = opvpArcPath; ++ procs.opvpDrawImage = opvpDrawImage; ++ procs.opvpStartDrawImage = opvpStartDrawImage; ++ procs.opvpTransferDrawImage = opvpTransferDrawImage; ++ procs.opvpEndDrawImage = opvpEndDrawImage; ++ procs.opvpStartScanline = opvpStartScanline; ++ procs.opvpScanline = opvpScanline; ++ procs.opvpEndScanline = opvpEndScanline; ++ procs.opvpStartRaster = opvpStartRaster; ++ procs.opvpTransferRasterData = opvpTransferRasterData; ++ procs.opvpSkipRaster = opvpSkipRaster; ++ procs.opvpEndRaster = opvpEndRaster; ++ procs.opvpStartStream = opvpStartStream; ++ procs.opvpTransferStreamData = opvpTransferStreamData; ++ procs.opvpEndStream = opvpEndStream; ++ ++ *apiProcs = &procs; ++ ++ OPVP_F2FIX(1.0, fixed_value); ++ ++ opv_gstate.ctm.a = 1.0; ++ opv_gstate.ctm.b = 0.0; ++ opv_gstate.ctm.c = 0.0; ++ opv_gstate.ctm.d = 1.0; ++ opv_gstate.ctm.e = 0.0; ++ opv_gstate.ctm.f = 0.0; ++ opv_gstate.colorspace = OPVP_CSPACE_DEVICERGB; ++ opv_gstate.fill_mode = OPVP_FILLMODE_EVENODD; ++ opv_gstate.alpha = 1.0; ++ opv_gstate.line_width = fixed_value; ++ opv_gstate.line_dash_n = 0; ++ opv_gstate.line_dash_array = NULL; ++ opv_gstate.dash_offset = fixed_value; ++ opv_gstate.line_style = OPVP_LINESTYLE_SOLID; ++ opv_gstate.line_cap = OPVP_LINECAP_BUTT; ++ opv_gstate.line_join = OPVP_LINEJOIN_MITER; ++ opv_gstate.miter_limit = fixed_value; ++ opv_gstate.paintmode = OPVP_PAINTMODE_OPAQUE; ++ opv_gstate.colorspace = OPVP_CSPACE_DEVICERGB; ++ ++ pFile = fopen("opvp_command_dump.txt","w"); ++ if (pFile != NULL) ++ { ++ fputs("opvpOpenPrinter\n", pFile); ++ return 0; ++ } ++ return -1; ++} +-- +2.40.0 diff --git a/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0002.patch b/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0002.patch new file mode 100644 index 0000000000..6ac25f0d71 --- /dev/null +++ b/meta/recipes-extended/ghostscript/ghostscript/CVE-2024-33871-0002.patch @@ -0,0 +1,43 @@ +From 7145885041bb52cc23964f0aa2aec1b1c82b5908 Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Mon, 22 Apr 2024 13:33:47 +0100 +Subject: [PATCH 7/7] OPVP device - prevent unsafe parameter change with SAFER + +Bug #707754 "OPVP device - Arbitrary code execution via custom Driver library" + +The "Driver" parameter for the "opvp"/"oprp" device specifies the name +of a dynamic library and allows any library to be loaded. + +The patch does not allow changing this parameter after activating path +control. + +This addresses CVE-2024-33871 + +CVE: CVE-2024-33871 + +Upstream-Status: Backport [https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=7145885041bb52cc2396] + +Signed-off-by: Archana Polampalli +--- + contrib/opvp/gdevopvp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c +index 64afbfe..f49a380 100644 +--- a/contrib/opvp/gdevopvp.c ++++ b/contrib/opvp/gdevopvp.c +@@ -3453,6 +3453,12 @@ _put_params(gx_device *dev, gs_param_list *plist) + code = param_read_string(plist, pname, &vdps); + switch (code) { + case 0: ++ if (gs_is_path_control_active(dev->memory) ++ && (!opdev->globals.vectorDriver || strlen(opdev->globals.vectorDriver) != vdps.size ++ || memcmp(opdev->globals.vectorDriver, vdps.data, vdps.size) != 0)) { ++ param_signal_error(plist, pname, gs_error_invalidaccess); ++ return_error(gs_error_invalidaccess); ++ } + buff = realloc(buff, vdps.size + 1); + memcpy(buff, vdps.data, vdps.size); + buff[vdps.size] = 0; +-- +2.40.0 diff --git a/meta/recipes-extended/ghostscript/ghostscript_9.55.0.bb b/meta/recipes-extended/ghostscript/ghostscript_9.55.0.bb index 083ee4b337..36c5aa3285 100644 --- a/meta/recipes-extended/ghostscript/ghostscript_9.55.0.bb +++ b/meta/recipes-extended/ghostscript/ghostscript_9.55.0.bb @@ -46,6 +46,8 @@ SRC_URI_BASE = "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/d file://CVE-2024-33870.patch \ file://CVE-2024-33869-0001.patch \ file://CVE-2024-33869-0002.patch \ + file://CVE-2024-33871-0001.patch \ + file://CVE-2024-33871-0002.patch \ " SRC_URI = "${SRC_URI_BASE} \