1 /* Copyright (c) 2003-2004, AXE, Inc.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /* $Id: gdevopvp.c 728 2008-03-03 02:56:05Z sho-otani $ */
20 /* gdevopvp.c  ver.1.00 rel.1.0     26 Nov 2004 */
21 /* OpenPrinting Vector Printer Driver Glue Code */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <locale.h>
28 #include <langinfo.h>
29 #include <dlfcn.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 
34 /* Set compatibility flag just in case we have GNU iconv.h */
35 #ifndef USE_LIBICONV_GNU
36 #  define LIBICONV_PLUG
37 #endif
38 #include <iconv.h>
39 
40 #include "string_.h"
41 #include "math_.h"
42 #include "gx.h"
43 #include "ghost.h"
44 #include "gscdefs.h"
45 #include "gsexit.h"
46 #include "gsstruct.h"
47 #include "gserrors.h"
48 #include "gsmatrix.h"
49 #include "gsparam.h"
50 #include "gxdevice.h"
51 #include "gxdcconv.h"
52 #include "gscspace.h"
53 #include "gsutil.h"
54 #include "gdevprn.h"
55 #include "gdevvec.h"
56 #include "spprint.h"
57 #include "ghost.h"
58 #include "gzstate.h"
59 #include "ialloc.h"
60 #include "iddict.h"
61 #include "dstack.h"
62 #include "ilevel.h"
63 #include "iinit.h"
64 #include "iname.h"
65 #include "imemory.h"
66 #include "igstate.h"
67 #include "interp.h"
68 #include "ipacked.h"
69 #include "iparray.h"
70 #include "iutil.h"
71 #include "ivmspace.h"
72 #include "opdef.h"
73 #include "store.h"
74 #include "gspath.h"
75 #include "gzpath.h"
76 #include "gzcpath.h"
77 #include "gsropt.h"
78 #include "gsiparam.h"
79 #include "gxxfont.h"
80 
81 /* added for image gamma correction */
82 #include "gximage.h"
83 #include "gxfmap.h"
84 #include "gxfrac.h"
85 #include "gxcvalue.h"
86 
87 #include "opvp_common.h"
88 
89 #define ENABLE_SIMPLE_MODE      1
90 #define ENABLE_SKIP_RASTER      1
91 #define ENABLE_AUTO_REVERSE     1
92 
93 /* ----- data types/macros ----- */
94 
95 /* for debug */
96 #ifdef  printf
97 #undef  printf
98 #endif
99 #ifdef  fprintf
100 #undef  fprintf
101 #endif
102 
103 /* buffer */
104 #define OPVP_BUFF_SIZE  1024
105 
106 /* ROP */
107 #define OPVP_0_2_ROP_S  0xCC
108 #define OPVP_0_2_ROP_P  0xF0
109 #define OPVP_0_2_ROP_OR 0xB8
110 
111 /* paper */
112 #define PS_DPI          72
113 #define MMPI            25.4
114 #define TOLERANCE       3.0
115 
116 typedef struct {
117     const char *region;
118     const char *name;
119     float width;
120     float height;
121 } OPVP_Paper;
122 
123 #define X_DPI           300
124 #define Y_DPI           300
125 
126 #define MAX_PATH_POINTS 1000
127 
128 /* driver */
129 typedef struct  gx_device_opvp_s {
130     gx_device_vector_common;
131 } gx_device_opvp;
132 
133 typedef struct  gx_device_oprp_s {
134     gx_device_common;
135     gx_prn_device_common;
136 } gx_device_oprp;
137 
138 /* point (internal) */
139 typedef struct {
140     floatp x;
141     floatp y;
142 } _fPoint;
143 
144 /* ----- private function prototypes ----- */
145 
146 /* Utilities */
147 static  int opvp_startpage(gx_device *);
148 static  int opvp_endpage(void);
149 static  char *opvp_alloc_string(char **, const char *);
150 static  char *opvp_cat_string(char **, const char *);
151 static  char *opvp_adjust_num_string(char *);
152 static  char **opvp_gen_dynamic_lib_name(void);
153 static  char *opvp_to_utf8(char *);
154 #define opvp_check_in_page(pdev)        \
155                 ((beginPage) || (inkjet) ? 0 \
156                     : (*vdev_proc(pdev, beginpage))((gx_device_vector*)pdev))
157 static  int opvp_get_papertable_index(gx_device *);
158 static  char *opvp_get_sizestring(float, float);
159 /* not used     static  const char *opvp_get_papersize_region(gx_device *);*/
160 /* not used     static  const char *opvp_get_papersize_name(gx_device *);*/
161 /* not used     static  char *opvp_get_papersize_inch(gx_device *);*/
162 /* not used     static  const char *opvp_get_papersize(gx_device *);*/
163 static  char *opvp_get_mediasize(gx_device *);
164 static  char *opvp_gen_page_info(gx_device *);
165 static  char *opvp_gen_doc_info(gx_device *);
166 static  char *opvp_gen_job_info(gx_device *);
167 static  int opvp_set_brush_color(gx_device_opvp *, gx_color_index,
168                                  opvp_brush_t *);
169 static  int opvp_draw_image(gx_device_opvp *, int,
170                             int, int, int, int, int, int, const byte *);
171 
172 /* load/unload vector driver */
173 static  int opvp_load_vector_driver(void);
174 static  int opvp_unload_vector_driver(void);
175 static  int prepare_open(gx_device *);
176 
177 /* driver procs */
178 static  int opvp_open(gx_device *);
179 static  int oprp_open(gx_device *);
180 static  void opvp_get_initial_matrix(gx_device *, gs_matrix *);
181 static  int opvp_output_page(gx_device *, int, int);
182 static  int opvp_close(gx_device *);
183 #if GS_VERSION_MAJOR >= 8
184 static  gx_color_index opvp_map_rgb_color(gx_device *, const gx_color_value *); /* modified for gs 8.15 */
185 #else
186 static  gx_color_index opvp_map_rgb_color(gx_device *, gx_color_value,
187                        gx_color_value, gx_color_value);
188 #endif
189 static  int opvp_map_color_rgb(gx_device *, gx_color_index, gx_color_value *);
190 static  int opvp_copy_mono(gx_device *, const byte *, int, int,
191                            gx_bitmap_id, int, int, int, int,
192                            gx_color_index, gx_color_index);
193 static  int opvp_copy_color(gx_device *, const byte *, int, int,
194                             gx_bitmap_id, int, int, int, int);
195 static  int _get_params(gs_param_list *);
196 static  int opvp_get_params(gx_device *, gs_param_list *);
197 static  int oprp_get_params(gx_device *, gs_param_list *);
198 static  int _put_params(gs_param_list *);
199 static  int opvp_put_params(gx_device *, gs_param_list *);
200 static  int oprp_put_params(gx_device *, gs_param_list *);
201 static  int opvp_fill_path(gx_device *, const gs_imager_state *, gx_path *,
202                            const gx_fill_params *, const gx_device_color *,
203                            const gx_clip_path *);
204 static  int opvp_stroke_path(gx_device *, const gs_imager_state *, gx_path *,
205                              const gx_stroke_params *, const gx_drawing_color *,
206                              const gx_clip_path *);
207 static  int opvp_fill_mask(gx_device *, const byte *, int, int, gx_bitmap_id,
208                            int, int, int, int, const gx_drawing_color *,
209                            int, gs_logical_operation_t, const gx_clip_path *);
210 
211 /* available color spaces */
212 
213 static char cspace_available[] = {
214         0, /* OPVP_CSPACE_BW */
215         0, /* OPVP_CSPACE_DEVICEGRAY */
216         0, /* OPVP_CSPACE_DEVICECMY */
217         0, /* OPVP_CSPACE_DEVICECMYK */
218         0, /* OPVP_CSPACE_DEVICERGB */
219         0, /* OPVP_CSPACE_DEVICEKRGB */
220         1, /* OPVP_CSPACE_STANDARDRGB */
221         0 /* OPVP_CSPACE_STANDARDRGB64 */
222 };
223 
224 /* vector driver procs */
225 static  int opvp_beginpage(gx_device_vector *);
226 static  int opvp_setlinewidth(gx_device_vector *, floatp);
227 static  int opvp_setlinecap(gx_device_vector *, gs_line_cap);
228 static  int opvp_setlinejoin(gx_device_vector *, gs_line_join);
229 static  int opvp_setmiterlimit(gx_device_vector *, floatp);
230 static  int opvp_setdash(gx_device_vector *, const float *, uint, floatp);
231 static  int opvp_setflat(gx_device_vector *, floatp);
232 static  int opvp_setlogop(gx_device_vector *, gs_logical_operation_t,
233                           gs_logical_operation_t);
234 #if GS_VERSION_MAJOR >= 8
235 static  int opvp_can_handle_hl_color(gx_device_vector *, const gs_imager_state *, const gx_drawing_color *);
236 static  int opvp_setfillcolor(gx_device_vector *, const gs_imager_state *, const gx_drawing_color *);
237 static  int opvp_setstrokecolor(gx_device_vector *, const gs_imager_state *,const gx_drawing_color *);
238 #else
239 static  int opvp_setfillcolor(gx_device_vector *, const gx_drawing_color *);
240 static  int opvp_setstrokecolor(gx_device_vector *, const gx_drawing_color *);
241 #endif
242 static  int opvp_vector_dopath(gx_device_vector *, const gx_path *,
243                                gx_path_type_t, const gs_matrix *);
244 static  int opvp_vector_dorect(gx_device_vector *, fixed, fixed, fixed, fixed,
245                                gx_path_type_t);
246 static  int opvp_beginpath(gx_device_vector *, gx_path_type_t);
247 static  int opvp_moveto(gx_device_vector *, floatp, floatp, floatp, floatp,
248                         gx_path_type_t);
249 static  int opvp_lineto(gx_device_vector *, floatp, floatp, floatp, floatp,
250                         gx_path_type_t);
251 static  int opvp_curveto(gx_device_vector *, floatp, floatp, floatp, floatp,
252                          floatp, floatp, floatp, floatp, gx_path_type_t);
253 static  int opvp_closepath(gx_device_vector *, floatp, floatp, floatp, floatp,
254                            gx_path_type_t);
255 static  int opvp_endpath(gx_device_vector *, gx_path_type_t);
256 
257 /* ----- Paper definition ----- */
258 OPVP_Paper      paperTable[] =
259 {
260 #if 0
261         {"jpn","hagaki",100/MMPI*PS_DPI,148/MMPI*PS_DPI},
262         {"iso","a6"    ,105/MMPI*PS_DPI,148/MMPI*PS_DPI},
263         {"jis","b6"    ,128/MMPI*PS_DPI,182/MMPI*PS_DPI},
264         {"jpn","oufuku",148/MMPI*PS_DPI,200/MMPI*PS_DPI},
265         {"iso","a5"    ,148/MMPI*PS_DPI,210/MMPI*PS_DPI},
266         {"jis","b5"    ,182/MMPI*PS_DPI,257/MMPI*PS_DPI},
267         {"iso","a4"    ,210/MMPI*PS_DPI,297/MMPI*PS_DPI},
268         {"na" ,"letter",     8.5*PS_DPI,      11*PS_DPI},/* 215.9x279.4 */
269         {"na" ,"legal" ,     8.5*PS_DPI,      14*PS_DPI},/* 215.9x355.6 */
270         {"jis","b4"    ,257/MMPI*PS_DPI,364/MMPI*PS_DPI},
271         {"iso","a3"    ,297/MMPI*PS_DPI,420/MMPI*PS_DPI},
272 #else
273 #include "opvp_media.def"
274 #endif
275         {NULL ,NULL    ,              0,              0}
276 };
277 
278 /* ----- Driver definition ----- */
279 
280 /* Driver procedures */
281 static  dev_proc_open_device(opvp_open);
282 static  dev_proc_open_device(oprp_open);
283 static  dev_proc_output_page(opvp_output_page);
284 static  dev_proc_print_page(oprp_print_page);
285 static  dev_proc_close_device(opvp_close);
286 static  dev_proc_get_params(opvp_get_params);
287 static  dev_proc_get_params(oprp_get_params);
288 static  dev_proc_put_params(opvp_put_params);
289 static  dev_proc_put_params(oprp_put_params);
290 static  dev_proc_fill_rectangle(opvp_fill_rectangle);
291 static  dev_proc_begin_image(opvp_begin_image);
292 static  image_enum_proc_plane_data(opvp_image_plane_data);
293 static  image_enum_proc_end_image(opvp_image_end_image);
294 
295 gs_public_st_suffix_add0_final(
296     st_device_opvp,
297     gx_device_opvp,
298     "gx_device_opvp",
299     device_opvp_enum_ptrs,
300     device_opvp_reloc_ptrs,
301     gx_device_finalize,
302     st_device_vector
303 );
304 
305 #define opvp_initial_values     \
306     NULL, /* *vectorDriver */\
307     NULL, /* *printerModel */\
308     NULL, /* *handle */\
309     NULL, /* (*OpenPrinter)() */\
310     NULL, /* *ErrorNo */\
311     -1, /* outputFD */\
312     0,  /* nApiEntry */\
313     NULL, /* *apiEntry */\
314     -1, /* printerContext */\
315     NULL, /* *jobInfo */\
316     NULL /* *docInfo */
317 
318 /* device procs */
319 #define opvp_procs \
320 {\
321     opvp_open,\
322     opvp_get_initial_matrix,\
323     NULL, /* sync_output */\
324     opvp_output_page,\
325     opvp_close,\
326     opvp_map_rgb_color,\
327     opvp_map_color_rgb,\
328     opvp_fill_rectangle, /*gdev_vector_fill_rectangle,*/\
329     NULL, /* tile_rectangle OBSOLETE */\
330     opvp_copy_mono,\
331     opvp_copy_color,\
332     NULL, /* draw_line OBSOLETE */\
333     NULL, /* get_bits */\
334     opvp_get_params,\
335     opvp_put_params,\
336     NULL, /* map_cmyk_color */\
337     NULL, /* get_xfont_procs */\
338     NULL, /* get_xfont_device */\
339     NULL, /* map_rgb_alpha_color */\
340     gx_page_device_get_page_device,\
341     NULL, /* get_alpha_bits OBSOLETE */\
342     NULL, /* copy_alpha */\
343     NULL, /* get_band */\
344     NULL, /* copy_rop */\
345     opvp_fill_path,\
346     opvp_stroke_path,\
347     opvp_fill_mask,\
348     gdev_vector_fill_trapezoid,\
349     gdev_vector_fill_parallelogram,\
350     gdev_vector_fill_triangle,\
351     NULL, /* draw_thin_line */\
352     opvp_begin_image,\
353     NULL, /* image_data */\
354     NULL, /* end_image */\
355     NULL, /* strip_tile_rectangle */\
356     NULL, /* strip_copy_rop */\
357     NULL, /* get_clipping_box */\
358     NULL, /* begin_typed_image */\
359     NULL, /* get_bits_rectangle */\
360     NULL, /* map_color_rgb_alpha */\
361     NULL, /* create_compositor */\
362     NULL, /* get_hardware_params */\
363     NULL, /* text_begin */\
364     NULL, /* finish_copydevice */\
365     NULL, /* begin_transparency_group */\
366     NULL, /* end_transparency_group */\
367     NULL, /* begin_transparency_mask */\
368     NULL, /* end_transparency_mask */\
369     NULL  /* discard_transparency_layer */\
370 }
371 
372 /* vector procs */
373 static  gx_device_vector_procs  opvp_vector_procs =
374 {
375     /* Page management */
376     opvp_beginpage,
377     /* Imager state */
378     opvp_setlinewidth,
379     opvp_setlinecap,
380     opvp_setlinejoin,
381     opvp_setmiterlimit,
382     opvp_setdash,
383     opvp_setflat,
384     opvp_setlogop,
385     /* Other state */
386 #if GS_VERSION_MAJOR >= 8
387     opvp_can_handle_hl_color,           /* added for gs 8.15 */
388 #endif
389     opvp_setfillcolor,
390     opvp_setstrokecolor,
391     /* Paths */
392     opvp_vector_dopath,
393     opvp_vector_dorect,
394     opvp_beginpath,
395     opvp_moveto,
396     opvp_lineto,
397     opvp_curveto,
398     opvp_closepath,
399     opvp_endpath
400 };
401 
402 const   gx_device_opvp          gs_opvp_device =
403 {
404     std_device_dci_type_body(
405         gx_device_opvp,
406         0,
407         "opvp",
408         &st_device_opvp,
409         DEFAULT_WIDTH_10THS_A4  * X_DPI / 10,
410         DEFAULT_HEIGHT_10THS_A4 * Y_DPI / 10,
411         X_DPI,
412         Y_DPI,
413         3,
414         24,
415         255,
416         255,
417         256,
418         256
419     ),
420     opvp_procs
421 };
422 
423 /* for inkjet */
424 static  gx_device_procs prn_oprp_procs =
425     prn_color_params_procs(
426         oprp_open,
427         opvp_output_page,
428         opvp_close,
429         opvp_map_rgb_color,
430         opvp_map_color_rgb,
431         oprp_get_params,
432         oprp_put_params
433     );
434 
435 const gx_device_oprp gs_oprp_device =
436 {
437     prn_device_std_margins_body(
438         gx_device_oprp,
439         prn_oprp_procs,
440         "oprp",
441         DEFAULT_WIDTH_10THS_A4,
442         DEFAULT_HEIGHT_10THS_A4,
443         X_DPI,
444         Y_DPI,
445         0, 0, 0, 0, 0, 0,
446         24,
447         oprp_print_page
448     )
449 };
450 
451 /* driver mode */
452 static bool vector = true;
453 static bool inkjet = false;
454 static char *vectorDriver = NULL;
455 static char *printerModel = NULL;
456 static void *handle = NULL;
457 static opvp_dc_t (*OpenPrinter)(opvp_int_t,const opvp_char_t*,
458                                   const opvp_int_t[2],
459                                   opvp_api_procs_t**) = NULL;
460 static int (*OpenPrinter_0_2)(int,char*,int*,
461                                   OPVP_api_procs**) = NULL;
462 static opvp_int_t *ErrorNo = NULL;
463 static opvp_int_t outputFD = -1;
464 static opvp_int_t nApiEntry = 0;
465 static opvp_api_procs_t *apiEntry = NULL;
466 static OPVP_api_procs *apiEntry_0_2 = NULL;
467 static opvp_dc_t printerContext = -1;
468 static char *jobInfo = NULL;
469 static char *docInfo = NULL;
470 static opvp_cspace_t colorSpace = OPVP_CSPACE_STANDARDRGB;
471 static opvp_cspace_t savedColorSpace;
472 static opvp_brush_t *vectorFillColor = NULL;
473 static float margins[4] = {0, 0, 0, 0};
474 static float zoom[2] = {1, 1};
475 static float shift[2] = {0, 0};
476 static bool zoomAuto = false;
477 static bool zooming = false;
478 static bool beginPage = false;
479 
480 static int
GetLastError_1_0(void)481 GetLastError_1_0(void)
482 {
483     return *ErrorNo;
484 }
485 
486 static int (*GetLastError)(void) = GetLastError_1_0;
487 
488 /* Wrapper functions that keep compatible with 0.2 */
489 
490 /* color space mapping 0.2 to 1.0 */
491 static opvp_cspace_t cspace_0_2_to_1_0[] = {
492     OPVP_CSPACE_BW,
493     OPVP_CSPACE_DEVICEGRAY,
494     OPVP_CSPACE_DEVICECMY,
495     OPVP_CSPACE_DEVICECMYK,
496     OPVP_CSPACE_DEVICERGB,
497     OPVP_CSPACE_STANDARDRGB,
498     OPVP_CSPACE_STANDARDRGB64
499 };
500 
501 /* color space mapping 1.0 to 0.2 */
502 static opvp_cspace_t cspace_1_0_to_0_2[] = {
503     OPVP_cspaceBW,
504     OPVP_cspaceDeviceGray,
505     OPVP_cspaceDeviceCMY,
506     OPVP_cspaceDeviceCMYK,
507     OPVP_cspaceDeviceRGB,
508     0, /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */
509     OPVP_cspaceStandardRGB,
510     OPVP_cspaceStandardRGB64,
511 };
512 
513 /* image format mapping 1.0 to 0.2 */
514 static opvp_imageformat_t iformat_1_0_to_0_2[] = {
515     OPVP_iformatRaw,
516     OPVP_iformatRaw, /* OPVP_IFORMAT_MASK use iformat raw in 0.2 */
517     OPVP_iformatRLE,
518     OPVP_iformatJPEG,
519     OPVP_iformatPNG,
520 };
521 /* image colorDepth needed in 0.2 */
522 static int colorDepth_0_2[] = {
523     1, /* OPVP_CSPACE_BW */
524     8, /* OPVP_CSPACE_DEVICEGRAY */
525     24, /* OPVP_CSPACE_DEVICECMY */
526     32, /* OPVP_CSPACE_DEVICECMYK */
527     24, /* OPVP_CSPACE_DEVICERGB */
528     32, /* OPVP_CSPACE_DEVICEKRGB */
529     24, /* OPVP_CSPACE_STANDARDRGB */
530     64, /* OPVP_CSPACE_STANDARDRGB64 */
531 };
532 
533 /* translate error code */
534 static int
GetLastError_0_2(void)535 GetLastError_0_2(void)
536 {
537     switch(*ErrorNo) {
538     case OPVP_FATALERROR_0_2:
539         return OPVP_FATALERROR;
540         break;
541     case OPVP_BADREQUEST_0_2:
542         return OPVP_BADREQUEST;
543         break;
544     case OPVP_BADCONTEXT_0_2:
545         return OPVP_BADCONTEXT;
546         break;
547     case OPVP_NOTSUPPORTED_0_2:
548         return OPVP_NOTSUPPORTED;
549         break;
550     case OPVP_JOBCANCELED_0_2:
551         return OPVP_JOBCANCELED;
552         break;
553     case OPVP_PARAMERROR_0_2:
554         return OPVP_PARAMERROR;
555         break;
556     default:
557         break;
558     }
559     /* unknown error no */
560     /* return FATALERROR instead */
561     return OPVP_FATALERROR;
562 }
563 
564 static opvp_result_t
StartPageWrapper(opvp_dc_t printerContext,const opvp_char_t * pageInfo)565 StartPageWrapper(opvp_dc_t printerContext, const opvp_char_t *pageInfo)
566 {
567     int r;
568 
569     if ((r = apiEntry_0_2->StartPage(printerContext,
570            /* discard const */(char *)pageInfo)) != OPVP_OK) {
571           /* error */
572         return r;
573     }
574     /* initialize ROP */
575     if (apiEntry_0_2->SetROP != NULL) {
576         apiEntry_0_2->SetROP(printerContext,
577           OPVP_0_2_ROP_P);
578     }
579     return OPVP_OK;
580 }
581 
582 static opvp_result_t
InitGSWrapper(opvp_dc_t printerContext)583 InitGSWrapper(opvp_dc_t printerContext)
584 {
585     int r;
586 
587     if ((r = apiEntry_0_2->InitGS(printerContext)) != OPVP_OK) {
588           /* error */
589         return r;
590     }
591     /* initialize ROP */
592     if (apiEntry_0_2->SetROP != NULL) {
593         apiEntry_0_2->SetROP(printerContext,
594           OPVP_0_2_ROP_P);
595     }
596     return OPVP_OK;
597 }
598 
599 static opvp_result_t
QueryColorSpaceWrapper(opvp_dc_t printerContext,opvp_int_t * pnum,opvp_cspace_t * pcspace)600 QueryColorSpaceWrapper( opvp_dc_t printerContext, opvp_int_t *pnum,
601     opvp_cspace_t *pcspace)
602 {
603     int r;
604     int i;
605 
606     if ((r = apiEntry_0_2->QueryColorSpace(printerContext,
607          (OPVP_ColorSpace *)pcspace,pnum)) != OPVP_OK) {
608         /* error */
609         return r;
610     }
611     /* translate cspaces */
612     for (i = 0;i < *pnum;i++) {
613         if (pcspace[i]
614              >= sizeof(cspace_0_2_to_1_0)/sizeof(opvp_cspace_t)) {
615             /* unknown color space */
616             /* set DEVICERGB instead */
617             pcspace[i] = OPVP_CSPACE_DEVICERGB;
618         } else {
619             pcspace[i] = cspace_0_2_to_1_0[pcspace[i]];
620         }
621     }
622     return OPVP_OK;
623 }
624 
625 static opvp_result_t
SetColorSpaceWrapper(opvp_dc_t printerContext,opvp_cspace_t cspace)626 SetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t cspace)
627 {
628     if (cspace == OPVP_CSPACE_DEVICEKRGB) {
629         /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */
630         *ErrorNo = OPVP_NOTSUPPORTED_0_2;
631         return -1;
632     }
633     if (cspace
634          >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) {
635         /* unknown color space */
636         *ErrorNo = OPVP_PARAMERROR_0_2;
637         return -1;
638     }
639     return  apiEntry_0_2->SetColorSpace(printerContext,
640       cspace_1_0_to_0_2[cspace]);
641 }
642 
643 static opvp_result_t
GetColorSpaceWrapper(opvp_dc_t printerContext,opvp_cspace_t * pcspace)644 GetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t *pcspace)
645 {
646     int r;
647 
648     if ((r = apiEntry_0_2->GetColorSpace(printerContext,
649       (OPVP_ColorSpace *)pcspace)) != OPVP_OK) {
650         /* error */
651         return r;
652     }
653     if (*pcspace
654          >= sizeof(cspace_0_2_to_1_0)/sizeof(opvp_cspace_t)) {
655         /* unknown color space */
656         /* set DEVICERGB instead */
657         *pcspace = OPVP_CSPACE_DEVICERGB;
658     } else {
659         *pcspace = cspace_0_2_to_1_0[*pcspace];
660     }
661     return r;
662 }
663 
664 static opvp_result_t
SetStrokeColorWrapper(opvp_dc_t printerContext,const opvp_brush_t * brush)665 SetStrokeColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush)
666 {
667     OPVP_Brush brush_0_2;
668 
669     if (brush == NULL) {
670         *ErrorNo = OPVP_PARAMERROR_0_2;
671         return -1;
672     }
673     if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) {
674         /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */
675         return OPVP_NOTSUPPORTED;
676     }
677     if (brush->colorSpace
678          >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) {
679         /* unknown color space */
680         *ErrorNo = OPVP_PARAMERROR_0_2;
681         return -1;
682     }
683     brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace];
684     brush_0_2.xorg = brush->xorg;
685     brush_0_2.yorg = brush->yorg;
686     brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush;
687     memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color));
688     return apiEntry_0_2->SetStrokeColor(printerContext,&brush_0_2);
689 }
690 
691 static opvp_result_t
SetFillColorWrapper(opvp_dc_t printerContext,const opvp_brush_t * brush)692 SetFillColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush)
693 {
694     OPVP_Brush brush_0_2;
695 
696     if (brush == NULL) {
697         *ErrorNo = OPVP_PARAMERROR_0_2;
698         return -1;
699     }
700     if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) {
701         /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */
702         return OPVP_NOTSUPPORTED;
703     }
704     if (brush->colorSpace
705          >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) {
706         /* unknown color space */
707         *ErrorNo = OPVP_PARAMERROR_0_2;
708         return -1;
709     }
710     brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace];
711     brush_0_2.xorg = brush->xorg;
712     brush_0_2.yorg = brush->yorg;
713     brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush;
714     memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color));
715     return apiEntry_0_2->SetFillColor(printerContext,&brush_0_2);
716 }
717 
718 static opvp_result_t
SetBgColorWrapper(opvp_dc_t printerContext,const opvp_brush_t * brush)719 SetBgColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush)
720 {
721     OPVP_Brush brush_0_2;
722 
723     if (brush == NULL) {
724         *ErrorNo = OPVP_PARAMERROR_0_2;
725         return -1;
726     }
727     if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) {
728         /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */
729         *ErrorNo = OPVP_NOTSUPPORTED_0_2;
730         return -1;
731     }
732     if (brush->colorSpace
733          >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) {
734         /* unknown color space */
735         *ErrorNo = OPVP_PARAMERROR_0_2;
736         return -1;
737     }
738     brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace];
739     brush_0_2.xorg = brush->xorg;
740     brush_0_2.yorg = brush->yorg;
741     brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush;
742     memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color));
743     return apiEntry_0_2->SetBgColor(printerContext,&brush_0_2);
744 }
745 
746 static opvp_result_t
DrawImageWrapper(opvp_dc_t printerContext,opvp_int_t sourceWidth,opvp_int_t sourceHeight,opvp_int_t sourcePitch,opvp_imageformat_t imageFormat,opvp_int_t destinationWidth,opvp_int_t destinationHeight,const void * imagedata)747 DrawImageWrapper(
748     opvp_dc_t printerContext,
749     opvp_int_t sourceWidth,
750     opvp_int_t sourceHeight,
751     opvp_int_t sourcePitch,
752     opvp_imageformat_t imageFormat,
753     opvp_int_t destinationWidth,
754     opvp_int_t destinationHeight,
755     const void *imagedata)
756 {
757     int r;
758     OPVP_Rectangle rect;
759     OPVP_ImageFormat iformat_0_2;
760     OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent;
761     int depth;
762 
763     if (imageFormat == OPVP_IFORMAT_MASK) {
764         if (apiEntry_0_2->GetPaintMode != NULL) {
765             apiEntry_0_2->GetPaintMode(printerContext,
766               &paintmode_0_2);
767         }
768         if (paintmode_0_2 != OPVP_paintModeTransparent) {
769             if (apiEntry_0_2->SetROP != NULL) {
770                 apiEntry_0_2->SetROP(printerContext,
771                     OPVP_0_2_ROP_S);
772             }
773         }
774         else {
775             if (apiEntry_0_2->SetROP != NULL) {
776                 apiEntry_0_2->SetROP(printerContext,
777                     OPVP_0_2_ROP_OR);
778             }
779         }
780         depth = 1;
781     } else {
782         if (apiEntry_0_2->SetROP != NULL) {
783             apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S);
784         }
785         depth = colorDepth_0_2[colorSpace];
786     }
787 
788     OPVP_I2FIX(0,rect.p0.x);
789     OPVP_I2FIX(0,rect.p0.y);
790     OPVP_I2FIX(destinationWidth,rect.p1.x);
791     OPVP_I2FIX(destinationHeight,rect.p1.y);
792     if (imageFormat >= sizeof(iformat_1_0_to_0_2)/sizeof(OPVP_ImageFormat)) {
793         /* illegal image format */
794         *ErrorNo = OPVP_PARAMERROR_0_2;
795         return -1;
796     }
797     iformat_0_2 = iformat_1_0_to_0_2[imageFormat];
798     r = apiEntry_0_2->DrawImage(printerContext,sourceWidth,sourceHeight,
799             depth,iformat_0_2,rect,
800             sourcePitch*sourceHeight,
801             /* remove const */ (void *)imagedata);
802 
803     if (apiEntry_0_2->SetROP != NULL) {
804         apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P);
805     }
806 
807     return r;
808 }
809 
810 static opvp_result_t
StartDrawImageWrapper(opvp_dc_t printerContext,opvp_int_t sourceWidth,opvp_int_t sourceHeight,opvp_int_t sourcePitch,opvp_imageformat_t imageFormat,opvp_int_t destinationWidth,opvp_int_t destinationHeight)811 StartDrawImageWrapper(
812     opvp_dc_t printerContext,
813     opvp_int_t sourceWidth,
814     opvp_int_t sourceHeight,
815     opvp_int_t sourcePitch,
816     opvp_imageformat_t imageFormat,
817     opvp_int_t destinationWidth,
818     opvp_int_t destinationHeight)
819 {
820     int r;
821     OPVP_Rectangle rect;
822     OPVP_ImageFormat iformat_0_2;
823     OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent;
824     int depth;
825 
826     if (imageFormat == OPVP_IFORMAT_MASK) {
827         if (apiEntry_0_2->GetPaintMode != NULL) {
828             apiEntry_0_2->GetPaintMode(printerContext,
829               &paintmode_0_2);
830         }
831         if (paintmode_0_2 != OPVP_paintModeTransparent) {
832             if (apiEntry_0_2->SetROP != NULL) {
833                 apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S);
834             }
835         }
836         else {
837             if (apiEntry_0_2->SetROP != NULL) {
838                 apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_OR);
839             }
840         }
841         depth = 1;
842     } else {
843         if (apiEntry_0_2->SetROP != NULL) {
844             apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S);
845         }
846         depth = colorDepth_0_2[colorSpace];
847     }
848 
849     OPVP_I2FIX(0,rect.p0.x);
850     OPVP_I2FIX(0,rect.p0.y);
851     OPVP_I2FIX(destinationWidth,rect.p1.x);
852     OPVP_I2FIX(destinationHeight,rect.p1.y);
853     if (imageFormat >= sizeof(iformat_1_0_to_0_2)/sizeof(OPVP_ImageFormat)) {
854         /* illegal image format */
855         *ErrorNo = OPVP_PARAMERROR_0_2;
856         return -1;
857     }
858     iformat_0_2 = iformat_1_0_to_0_2[imageFormat];
859     r = apiEntry_0_2->StartDrawImage(printerContext,
860             sourceWidth,sourceHeight,
861             depth,iformat_0_2,rect);
862 
863     return r;
864 }
865 
866 static opvp_result_t
EndDrawImageWrapper(opvp_dc_t printerContext)867 EndDrawImageWrapper(opvp_dc_t printerContext)
868 {
869     int r;
870 
871     r = apiEntry_0_2->EndDrawImage(printerContext);
872 
873     /* make sure rop is pattern copy */
874     if (apiEntry_0_2->SetROP != NULL) {
875         apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P);
876     }
877 
878     return r;
879 }
880 
881 static opvp_result_t
QueryDeviceCapabilityWrapper(opvp_dc_t printerContext,opvp_queryinfoflags_t queryflag,opvp_int_t * buflen,opvp_char_t * infoBuf)882 QueryDeviceCapabilityWrapper(
883     opvp_dc_t printerContext,
884     opvp_queryinfoflags_t queryflag,
885     opvp_int_t *buflen,
886     opvp_char_t *infoBuf)
887 {
888     return apiEntry_0_2->QueryDeviceCapability(printerContext,queryflag,
889       *buflen,(char *)infoBuf);
890 }
891 
892 static opvp_result_t
QueryDeviceInfoWrapper(opvp_dc_t printerContext,opvp_queryinfoflags_t queryflag,opvp_int_t * buflen,opvp_char_t * infoBuf)893 QueryDeviceInfoWrapper(
894     opvp_dc_t printerContext,
895     opvp_queryinfoflags_t queryflag,
896     opvp_int_t *buflen,
897     opvp_char_t *infoBuf)
898 {
899     if (queryflag & OPVP_QF_MEDIACOPY) {
900         *ErrorNo = OPVP_NOTSUPPORTED;
901         return -1;
902     }
903     if (queryflag & OPVP_QF_PRINTREGION) {
904         queryflag &= ~OPVP_QF_PRINTREGION;
905         queryflag |= 0x0020000;
906     }
907     return apiEntry_0_2->QueryDeviceInfo(printerContext,queryflag,
908       *buflen,(char *)infoBuf);
909 }
910 
911 static opvp_result_t
SetLineDashWrapper(opvp_dc_t printerContext,opvp_int_t num,const opvp_fix_t * pdash)912 SetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t num,
913     const opvp_fix_t *pdash)
914 {
915     return apiEntry_0_2->SetLineDash(printerContext,
916       /* remove const */ (OPVP_Fix *)pdash,num);
917 }
918 
919 static opvp_result_t
GetLineDashWrapper(opvp_dc_t printerContext,opvp_int_t * pnum,opvp_fix_t * pdash)920 GetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t *pnum,
921     opvp_fix_t *pdash)
922 {
923     return apiEntry_0_2->GetLineDash(printerContext,
924       pdash,pnum);
925 }
926 
927 static opvp_dc_t
OpenPrinterWrapper(opvp_int_t outputFD,const opvp_char_t * printerModel,const opvp_int_t apiVersion[2],opvp_api_procs_t ** apiProcs)928 OpenPrinterWrapper(
929     opvp_int_t outputFD,
930     const opvp_char_t *printerModel,
931     const opvp_int_t apiVersion[2],
932     opvp_api_procs_t **apiProcs)
933 {
934     opvp_dc_t dc = -1;
935 
936     if (OpenPrinter != NULL) {
937         dc = (*OpenPrinter)(outputFD,printerModel,apiVersion,apiProcs);
938     } else {
939         /* try version 0.2 */
940 
941         if (OpenPrinter_0_2 != NULL) {
942             static opvp_api_procs_t tEntry;
943             int nApiEntry;
944 
945             dc = (*OpenPrinter_0_2)(outputFD,
946                     /* remove const */
947                     (char *)printerModel,
948                     &nApiEntry,&apiEntry_0_2);
949             /* setting functions */
950             tEntry.opvpClosePrinter
951                     = apiEntry_0_2->ClosePrinter;
952             tEntry.opvpStartJob
953                     = (opvp_result_t (*)(opvp_int_t,
954                        const opvp_char_t*))
955                        apiEntry_0_2->StartJob;
956             tEntry.opvpEndJob = apiEntry_0_2->EndJob;
957             tEntry.opvpAbortJob = NULL;
958             tEntry.opvpStartDoc
959                     = (opvp_result_t (*)(opvp_dc_t,
960                        const opvp_char_t*))
961                        apiEntry_0_2->StartDoc;
962             tEntry.opvpEndDoc = apiEntry_0_2->EndDoc;
963             if (apiEntry_0_2->StartPage != NULL) {
964                 tEntry.opvpStartPage = StartPageWrapper;
965             } else {
966                 tEntry.opvpStartPage = NULL;
967             }
968             tEntry.opvpEndPage = apiEntry_0_2->EndPage;
969 
970             if (apiEntry_0_2->QueryDeviceCapability != NULL) {
971                 tEntry.opvpQueryDeviceCapability
972                   = QueryDeviceCapabilityWrapper;
973             } else {
974                 tEntry.opvpQueryDeviceCapability = NULL;
975             }
976 
977             if (apiEntry_0_2->QueryDeviceInfo != NULL) {
978                 tEntry.opvpQueryDeviceInfo = QueryDeviceInfoWrapper;
979             } else {
980                 tEntry.opvpQueryDeviceInfo = NULL;
981             }
982 
983             tEntry.opvpResetCTM = apiEntry_0_2->ResetCTM;
984             tEntry.opvpSetCTM = (opvp_result_t (*)(opvp_dc_t,
985                        const opvp_ctm_t*))
986                        apiEntry_0_2->SetCTM;
987             tEntry.opvpGetCTM = (opvp_result_t (*)(opvp_dc_t,opvp_ctm_t*))
988                        apiEntry_0_2->GetCTM;
989             if (apiEntry_0_2->InitGS != NULL) {
990                 tEntry.opvpInitGS = InitGSWrapper;
991             } else {
992                 tEntry.opvpInitGS = NULL;
993             }
994             tEntry.opvpSaveGS = apiEntry_0_2->SaveGS;
995             tEntry.opvpRestoreGS = apiEntry_0_2->RestoreGS;
996             if (apiEntry_0_2->QueryColorSpace != NULL) {
997                 tEntry.opvpQueryColorSpace = QueryColorSpaceWrapper;
998             } else {
999                 tEntry.opvpQueryColorSpace = NULL;
1000             }
1001             if (apiEntry_0_2->SetColorSpace != NULL) {
1002                 tEntry.opvpSetColorSpace = SetColorSpaceWrapper;
1003             } else {
1004                 tEntry.opvpSetColorSpace = NULL;
1005             }
1006             if (apiEntry_0_2->GetColorSpace != NULL) {
1007                 tEntry.opvpGetColorSpace = GetColorSpaceWrapper;
1008             } else {
1009                 tEntry.opvpGetColorSpace = NULL;
1010             }
1011             tEntry.opvpSetFillMode
1012                     = (opvp_result_t (*)(opvp_dc_t,opvp_fillmode_t))
1013                        apiEntry_0_2->SetFillMode;
1014             tEntry.opvpGetFillMode
1015                     = (opvp_result_t (*)(opvp_dc_t,opvp_fillmode_t*))
1016                        apiEntry_0_2->GetFillMode;
1017             tEntry.opvpSetAlphaConstant = apiEntry_0_2->SetAlphaConstant;
1018             tEntry.opvpGetAlphaConstant = apiEntry_0_2->GetAlphaConstant;
1019             tEntry.opvpSetLineWidth = apiEntry_0_2->SetLineWidth;
1020             tEntry.opvpGetLineWidth = apiEntry_0_2->GetLineWidth;
1021             if (apiEntry_0_2->SetLineDash != NULL) {
1022                 tEntry.opvpSetLineDash = SetLineDashWrapper;
1023             } else {
1024                 tEntry.opvpSetLineDash = NULL;
1025             }
1026             if (apiEntry_0_2->GetLineDash != NULL) {
1027                 tEntry.opvpGetLineDash = GetLineDashWrapper;
1028             } else {
1029                 tEntry.opvpGetLineDash = NULL;
1030             }
1031             tEntry.opvpSetLineDashOffset
1032                     = apiEntry_0_2->SetLineDashOffset;
1033             tEntry.opvpGetLineDashOffset
1034                     = apiEntry_0_2->GetLineDashOffset;
1035             tEntry.opvpSetLineStyle
1036                     = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t))
1037                        apiEntry_0_2->SetLineStyle;
1038             tEntry.opvpGetLineStyle
1039                     = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t*))
1040                        apiEntry_0_2->GetLineStyle;
1041             tEntry.opvpSetLineCap
1042                     = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t))
1043                        apiEntry_0_2->SetLineCap;
1044             tEntry.opvpGetLineCap
1045                     = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t*))
1046                        apiEntry_0_2->GetLineCap;
1047             tEntry.opvpSetLineJoin
1048                     = (opvp_result_t (*)(opvp_dc_t,opvp_linejoin_t))
1049                        apiEntry_0_2->SetLineJoin;
1050             tEntry.opvpGetLineJoin
1051                     = (opvp_result_t (*)(opvp_dc_t,opvp_linejoin_t*))
1052                        apiEntry_0_2->GetLineJoin;
1053             tEntry.opvpSetMiterLimit = apiEntry_0_2->SetMiterLimit;
1054             tEntry.opvpGetMiterLimit = apiEntry_0_2->GetMiterLimit;
1055             tEntry.opvpSetPaintMode
1056                     = (opvp_result_t (*)(opvp_dc_t,opvp_paintmode_t))
1057                        apiEntry_0_2->SetPaintMode;
1058             tEntry.opvpGetPaintMode
1059                     = (opvp_result_t (*)(opvp_dc_t,opvp_paintmode_t*))
1060                        apiEntry_0_2->GetPaintMode;
1061             if (apiEntry_0_2->SetStrokeColor != NULL) {
1062                 tEntry.opvpSetStrokeColor = SetStrokeColorWrapper;
1063             } else {
1064                 tEntry.opvpSetStrokeColor = NULL;
1065             }
1066             if (apiEntry_0_2->SetFillColor != NULL) {
1067                 tEntry.opvpSetFillColor = SetFillColorWrapper;
1068             } else {
1069                 tEntry.opvpSetFillColor = NULL;
1070             }
1071             if (apiEntry_0_2->SetBgColor != NULL) {
1072                 tEntry.opvpSetBgColor = SetBgColorWrapper;
1073             } else {
1074                 tEntry.opvpSetBgColor = NULL;
1075             }
1076             tEntry.opvpNewPath = apiEntry_0_2->NewPath;
1077             tEntry.opvpEndPath = apiEntry_0_2->EndPath;
1078             tEntry.opvpStrokePath = apiEntry_0_2->StrokePath;
1079             tEntry.opvpFillPath = apiEntry_0_2->FillPath;
1080             tEntry.opvpStrokeFillPath = apiEntry_0_2->StrokeFillPath;
1081             tEntry.opvpSetClipPath
1082                     = (opvp_result_t (*)(opvp_dc_t,opvp_cliprule_t))
1083                        apiEntry_0_2->SetClipPath;
1084             tEntry.opvpResetClipPath = apiEntry_0_2->ResetClipPath;
1085             tEntry.opvpSetCurrentPoint = apiEntry_0_2->SetCurrentPoint;
1086             tEntry.opvpLinePath
1087                     = (opvp_result_t (*)(opvp_dc_t,
1088                        opvp_pathmode_t,opvp_int_t,
1089                        const opvp_point_t*))
1090                        apiEntry_0_2->LinePath;
1091             tEntry.opvpPolygonPath
1092                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1093                        const opvp_int_t*,
1094                        const opvp_point_t*))
1095                        apiEntry_0_2->PolygonPath;
1096             tEntry.opvpRectanglePath
1097                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1098                        const opvp_rectangle_t*))
1099                        apiEntry_0_2->RectanglePath;
1100             tEntry.opvpRoundRectanglePath
1101                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1102                        const opvp_roundrectangle_t*))
1103                        apiEntry_0_2->RoundRectanglePath;
1104             tEntry.opvpBezierPath
1105                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1106                        const opvp_point_t*))
1107                        apiEntry_0_2->BezierPath;
1108             tEntry.opvpArcPath
1109                     = (opvp_result_t (*)(opvp_dc_t,opvp_arcmode_t,
1110                        opvp_arcdir_t,opvp_fix_t,opvp_fix_t,opvp_fix_t,
1111                        opvp_fix_t,opvp_fix_t,opvp_fix_t,opvp_fix_t,
1112                        opvp_fix_t))apiEntry_0_2->ArcPath;
1113             if (apiEntry_0_2->DrawImage != NULL) {
1114                 tEntry.opvpDrawImage = DrawImageWrapper;
1115             } else {
1116                 tEntry.opvpDrawImage = NULL;
1117             }
1118             if (apiEntry_0_2->StartDrawImage != NULL) {
1119                 tEntry.opvpStartDrawImage = StartDrawImageWrapper;
1120             } else {
1121                 tEntry.opvpStartDrawImage = NULL;
1122             }
1123             tEntry.opvpTransferDrawImage =
1124                (opvp_result_t (*)(opvp_dc_t,opvp_int_t,const void*))
1125                apiEntry_0_2->TransferDrawImage;
1126             if (apiEntry_0_2->EndDrawImage != NULL) {
1127                 tEntry.opvpEndDrawImage = EndDrawImageWrapper;
1128             } else {
1129                 tEntry.opvpEndDrawImage = NULL;
1130             }
1131             tEntry.opvpStartScanline = apiEntry_0_2->StartScanline;
1132             tEntry.opvpScanline
1133                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1134                        const opvp_int_t*))
1135                        apiEntry_0_2->Scanline;
1136             tEntry.opvpEndScanline = apiEntry_0_2->EndScanline;
1137             tEntry.opvpStartRaster = apiEntry_0_2->StartRaster;
1138             tEntry.opvpTransferRasterData
1139                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1140                        const opvp_byte_t*))
1141                        apiEntry_0_2->TransferRasterData;
1142             tEntry.opvpSkipRaster = apiEntry_0_2->SkipRaster;
1143             tEntry.opvpEndRaster = apiEntry_0_2->EndRaster;
1144             tEntry.opvpStartStream = apiEntry_0_2->StartStream;
1145             tEntry.opvpTransferStreamData
1146                     = (opvp_result_t (*)(opvp_dc_t,opvp_int_t,
1147                        const void *))
1148                        apiEntry_0_2->TransferStreamData;
1149             tEntry.opvpEndStream = apiEntry_0_2->EndStream;
1150 
1151             *apiProcs = &tEntry;
1152 
1153             GetLastError = GetLastError_0_2;
1154         }
1155     }
1156     return dc;
1157 }
1158 
1159 /* for image */
1160 static  const
1161 gx_image_enum_procs_t opvp_image_enum_procs =
1162 {
1163     opvp_image_plane_data,
1164     opvp_image_end_image
1165 };
1166 typedef enum _FastImageSupportMode {
1167     FastImageDisable,
1168     FastImageNoCTM,
1169     FastImageNoRotate,
1170     FastImageRightAngle,
1171     FastImageReverseAngle,
1172     FastImageAll
1173 } FastImageSupportMode;
1174 static char *fastImage = NULL;
1175 static FastImageSupportMode FastImageMode = FastImageDisable;
1176 static bool begin_image = false;
1177 static bool change_paint_mode = false;
1178 static bool change_cspace = false;
1179 static gs_color_space_index color_index = 0;
1180 static gs_color_space_index base_color_index = 0;
1181 static byte palette[3*256];
1182 static float imageDecode[GS_IMAGE_MAX_COMPONENTS * 2];
1183 static bool reverse_image = false;
1184 
1185 /* added for image gamma correction */
1186 typedef struct bbox_image_enum_s {
1187     gx_image_enum_common;
1188 /*  gs_memory_t *memory; */
1189     gs_matrix matrix; /* map from image space to device dpace */
1190     const gx_clip_path *pcpath;
1191     gx_image_enum_common_t *target_info;
1192     bool params_are_const;
1193     int x0, x1;
1194     int y, height;
1195 } bbox_image_enum;
1196 
1197 /* The following is already defined in stdpre.h */
1198 /*#define       min(a, b) (((a) < (b))? (a) : (b))*/
1199 
1200 /* ----- Utilities ----- */
1201 
1202 /* initialize Graphic State */
1203 /* No defaults in OPVP 1.0 */
1204 static int
InitGS(void)1205 InitGS(void)
1206 {
1207     if (apiEntry->opvpInitGS != NULL) {
1208         if (apiEntry->opvpInitGS(printerContext) != OPVP_OK) {
1209             return -1;
1210         }
1211     }
1212     if (apiEntry->opvpSetColorSpace != NULL) {
1213         if (apiEntry->opvpSetColorSpace(printerContext,colorSpace)
1214            != OPVP_OK) {
1215             return -1;
1216         }
1217     }
1218     if (apiEntry->opvpSetPaintMode != NULL) {
1219         if (apiEntry->opvpSetPaintMode(printerContext,
1220             OPVP_PAINTMODE_TRANSPARENT) != OPVP_OK) {
1221             return -1;
1222         }
1223     }
1224     if (apiEntry->opvpSetAlphaConstant != NULL) {
1225         if (apiEntry->opvpSetAlphaConstant(printerContext,1.0)
1226            != OPVP_OK) {
1227             return -1;
1228         }
1229     }
1230 
1231     /* other properties are set by GhostScript */
1232     return 0;
1233 }
1234 
1235 static  int
opvp_startpage(gx_device * dev)1236 opvp_startpage(gx_device *dev)
1237 {
1238     int ecode = 0;
1239     opvp_result_t r = -1;
1240     static char *page_info = NULL;
1241 
1242     /* page info */
1243     page_info = opvp_alloc_string(&page_info, OPVP_INFO_PREFIX);
1244     page_info = opvp_cat_string(&page_info, opvp_gen_page_info(dev));
1245 
1246     /* call StartPage */
1247     if (printerContext != -1) {
1248         if (apiEntry->opvpStartPage)
1249             r = apiEntry->opvpStartPage(printerContext,
1250                        (opvp_char_t *)opvp_to_utf8(page_info));
1251         if (r != OPVP_OK) {
1252             ecode = -1;
1253         } else {
1254             ecode = InitGS();
1255         }
1256     }
1257 
1258     return ecode;
1259 }
1260 
1261 static  int
opvp_endpage(void)1262 opvp_endpage(void)
1263 {
1264     int ecode = 0;
1265     opvp_result_t r = -1;
1266 
1267     /* call EndPage */
1268     if (printerContext != -1) {
1269         if (apiEntry->opvpEndPage)
1270             r = apiEntry->opvpEndPage(printerContext);
1271         if (r != OPVP_OK) {
1272             ecode = -1;
1273         }
1274     }
1275 
1276     return ecode;
1277 }
1278 
1279 static  char *
opvp_alloc_string(char ** destin,const char * source)1280 opvp_alloc_string(char **destin, const char *source)
1281 {
1282     if (!destin) return NULL;
1283 
1284     if (*destin) {
1285         if (source) {
1286             *destin = realloc(*destin, strlen(source)+1);
1287         } else {
1288             free(*destin);
1289             *destin = NULL;
1290         }
1291     } else {
1292         if (source) {
1293             *destin = malloc(strlen(source)+1);
1294         }
1295     }
1296     if (*destin && source) {
1297         if (*destin != source) {
1298             strcpy(*destin, source);
1299         }
1300     }
1301 
1302     return *destin;
1303 }
1304 
1305 static  char *
opvp_cat_string(char ** destin,const char * string)1306 opvp_cat_string(char **destin, const char *string)
1307 {
1308     if (!destin) return NULL;
1309     if (!(*destin)) return opvp_alloc_string(destin, string);
1310 
1311     if (string) {
1312         *destin = realloc(*destin, strlen(*destin) +strlen(string)+1);
1313         strcat(*destin, string);
1314     }
1315 
1316     return *destin;
1317 }
1318 
1319 static  char *
opvp_adjust_num_string(char * num_string)1320 opvp_adjust_num_string(char *num_string)
1321 {
1322     char *pp;
1323     char *lp;
1324 
1325     if (!num_string) return NULL;
1326 
1327     if ((pp = strrchr(num_string, '.'))) {
1328         for (lp = &(num_string[strlen(num_string)-1]); lp > pp; lp--) {
1329             if (*lp == '0') {
1330                 *lp = '\0';
1331             } else {
1332                 break;
1333             }
1334         }
1335         if (lp == pp) *lp = '\0';
1336     }
1337 
1338     return num_string;
1339 }
1340 
1341 static  char **
opvp_gen_dynamic_lib_name(void)1342 opvp_gen_dynamic_lib_name(void)
1343 {
1344     static char *buff[5] = {NULL,NULL,NULL,NULL,NULL};
1345     char tbuff[OPVP_BUFF_SIZE];
1346 
1347     if (!vectorDriver) {
1348         return NULL;
1349     }
1350 
1351     memset((void*)tbuff, 0, OPVP_BUFF_SIZE);
1352     strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 1);
1353     opvp_alloc_string(&(buff[0]), tbuff);
1354 
1355     memset((void*)tbuff, 0, OPVP_BUFF_SIZE);
1356     strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 4);
1357     strcat(tbuff, ".so");
1358     opvp_alloc_string(&(buff[1]), tbuff);
1359 
1360     memset((void*)tbuff, 0, OPVP_BUFF_SIZE);
1361     strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 5);
1362     strcat(tbuff, ".dll");
1363     opvp_alloc_string(&(buff[2]), tbuff);
1364 
1365     memset((void*)tbuff, 0, OPVP_BUFF_SIZE);
1366     strcpy(tbuff, "lib");
1367     strncat(tbuff, vectorDriver, OPVP_BUFF_SIZE - 7);
1368     strcat(tbuff, ".so");
1369     opvp_alloc_string(&(buff[3]), tbuff);
1370 
1371     buff[4] = NULL;
1372 
1373     return buff;
1374 }
1375 
1376 static  char *
opvp_to_utf8(char * string)1377 opvp_to_utf8(char *string)
1378 {
1379     char *locale;
1380     iconv_t cd;
1381     char *buff = NULL;
1382     size_t ib, ob;
1383     int  complete = false;
1384     char *ibuff, *obuff;
1385     char *ostring = NULL;
1386 
1387     if (string) {
1388         ib = strlen(string);
1389         if (ib > 0) {
1390             ob = ib * 4;
1391             buff = malloc(ob+1);
1392             setlocale(LC_CTYPE, "");
1393 #ifdef CODESET
1394             locale = nl_langinfo(CODESET);
1395 #else
1396             locale = "UTF-8";
1397 #endif /* CODESET */
1398             if (locale) {
1399                 if (strcmp(locale, "C") && buff) {
1400                     if ((cd = iconv_open("UTF-8", locale)) != (iconv_t)-1) {
1401                         ibuff = string;
1402                         obuff = buff;
1403                         if (iconv(cd, &ibuff, &ib, &obuff, &ob) != -1) {
1404                             *obuff = 0;
1405                             complete = true;
1406                         }
1407                         iconv_close(cd);
1408                     }
1409                 }
1410             }
1411         }
1412     }
1413 
1414     if (complete) {
1415         ostring = opvp_alloc_string(&ostring, buff);
1416     } else {
1417         ostring = string;
1418     }
1419 
1420     if (buff) free(buff);
1421     return ostring;
1422 }
1423 
1424 static float
opvp_fabsf(float f)1425 opvp_fabsf(float f)
1426 {
1427     return (float)fabs((double)f);
1428 }
1429 
1430 static  int
opvp_get_papertable_index(gx_device * pdev)1431 opvp_get_papertable_index(gx_device *pdev)
1432 {
1433     int i;
1434     float width, height;
1435     bool landscape;
1436     float paper_w, paper_h;
1437     float prev = -1;
1438     int paper = -1;
1439     int candidate = -1;
1440     int smaller = -1;
1441     int larger  = -1;
1442     int s_candi = -1;
1443     int l_candi = -1;
1444     float h_delta = TOLERANCE;
1445     float sw_delta = TOLERANCE;
1446     float sh_delta = TOLERANCE;
1447     float lw_delta = TOLERANCE;
1448     float lh_delta = TOLERANCE;
1449     bool match = false;
1450     float f;
1451 
1452     /* portrait or landscape */
1453     landscape = (pdev->MediaSize[0] < pdev->MediaSize[1] ? false : true);
1454 
1455     /* paper size */
1456     width  = (landscape ? pdev->MediaSize[1] : pdev->MediaSize[0]);
1457     height = (landscape ? pdev->MediaSize[0] : pdev->MediaSize[1]);
1458 
1459     for (i=0; paperTable[i].name != NULL; i++) {
1460         paper_w = paperTable[i].width;
1461         paper_h = paperTable[i].height;
1462         if (width == paper_w) {
1463             if (height == paper_h) {
1464                 paper = i;
1465                 match = true;
1466                 break;
1467             } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) {
1468                 if (f < h_delta) {
1469                     h_delta = f;
1470                     candidate = i;
1471                 }
1472             }
1473         } else if (candidate != -1) {
1474             paper = candidate;
1475             match = true;
1476             break;
1477         } else if (prev != paper_w) {
1478             prev = paper_w;
1479             if (paper_w < width) {
1480                 if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) {
1481                     if (f < sw_delta) {
1482                         sw_delta = f;
1483                         smaller  = i;
1484                     }
1485                 }
1486             } else {
1487                 if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) {
1488                     if (f < lw_delta) {
1489                         lw_delta = f;
1490                         larger   = i;
1491                     }
1492                 }
1493             }
1494         }
1495     }
1496     if (!match) {
1497         paper = i;
1498         if (smaller != -1) {
1499             paper_w = paperTable[smaller].width;
1500             for (i = smaller; paperTable[i].width == paper_w; i++) {
1501                 paper_h = paperTable[i].height;
1502                 if (height == paper_h) {
1503                     sh_delta = 0;
1504                     s_candi  = i;
1505                     break;
1506                 } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) {
1507                     if (f < sh_delta) {
1508                         sh_delta = f;
1509                         s_candi  = i;
1510                     }
1511                 }
1512             }
1513         }
1514         if (larger != -1) {
1515             paper_w = paperTable[larger].width;
1516             for (i = larger; paperTable[i].width == paper_w; i++) {
1517                 paper_h = paperTable[i].height;
1518                 if (height == paper_h) {
1519                     lh_delta = 0;
1520                     l_candi  = i;
1521                     break;
1522                 } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) {
1523                     if (f < lh_delta) {
1524                         lh_delta = f;
1525                         l_candi  = i;
1526                     }
1527                 }
1528             }
1529         }
1530         if (s_candi != -1) {
1531             if (l_candi != -1) {
1532                 if ((sw_delta + sh_delta)
1533                   < (lw_delta + lh_delta)) {
1534                         paper = s_candi;
1535                 } else {
1536                         paper = l_candi;
1537                 }
1538             } else {
1539                 paper = s_candi;
1540             }
1541         } else {
1542             if (l_candi != -1) {
1543                 paper = l_candi;
1544             }
1545         }
1546     }
1547 
1548     return paper;
1549 }
1550 
1551 static  char *
opvp_get_sizestring(float width,float height)1552 opvp_get_sizestring(float width, float height)
1553 {
1554     char nbuff[OPVP_BUFF_SIZE];
1555     char nbuff1[OPVP_BUFF_SIZE / 2];
1556     char nbuff2[OPVP_BUFF_SIZE / 2];
1557     static char *buff = NULL;
1558 
1559     memset((void*)nbuff, 0, OPVP_BUFF_SIZE);
1560     memset((void*)nbuff1, 0, OPVP_BUFF_SIZE / 2);
1561     memset((void*)nbuff2, 0, OPVP_BUFF_SIZE / 2);
1562 
1563     snprintf(nbuff1, OPVP_BUFF_SIZE / 2 - 1, "%.3f", width);
1564     snprintf(nbuff2, OPVP_BUFF_SIZE / 2 - 1, "%.3f", height);
1565     snprintf(nbuff, OPVP_BUFF_SIZE - 1, "%sx%s",
1566                 opvp_adjust_num_string(nbuff1),
1567                 opvp_adjust_num_string(nbuff2));
1568 
1569     return opvp_alloc_string(&buff, nbuff);
1570 }
1571 
1572 static  char *
opvp_get_mediasize(gx_device * pdev)1573 opvp_get_mediasize(gx_device *pdev)
1574 {
1575     int i;
1576     char wbuff[OPVP_BUFF_SIZE];
1577     static char *buff = NULL;
1578     const char *region;
1579     const char *name;
1580     float width;
1581     float height;
1582     const char *unit;
1583     bool landscape;
1584 
1585     i = opvp_get_papertable_index(pdev);
1586 
1587     if (paperTable[i].name) {
1588         region = paperTable[i].region;
1589         name   = paperTable[i].name;
1590         width  = paperTable[i].width  / PS_DPI;
1591         height = paperTable[i].height / PS_DPI;
1592         if((strcmp(region, "na"  ) == 0) ||
1593            (strcmp(region, "asme") == 0) ||
1594            (strcmp(region, "roc" ) == 0) ||
1595            (strcmp(region, "oe"  ) == 0)) {
1596             unit    = "in";
1597         } else {
1598             width  *= MMPI;
1599             height *= MMPI;
1600             unit    = "mm";
1601         }
1602     } else {
1603         landscape = (pdev->MediaSize[0] < pdev->MediaSize[1] ?
1604                      false : true);
1605         region = "custom";
1606         name   = "opvp";
1607         width  = (landscape ? pdev->MediaSize[1] : pdev->MediaSize[0])
1608                / PS_DPI;
1609         height = (landscape ? pdev->MediaSize[0] : pdev->MediaSize[1])
1610                / PS_DPI;
1611         unit   = "in";
1612     }
1613     memset((void*)wbuff, 0, OPVP_BUFF_SIZE);
1614     snprintf(wbuff, OPVP_BUFF_SIZE - 1, "%s_%s_%s%s", region, name,
1615                                  opvp_get_sizestring(width, height),
1616                                  unit);
1617     buff = opvp_alloc_string(&buff, wbuff);
1618 
1619     return buff;
1620 }
1621 
1622 static  char *
opvp_gen_page_info(gx_device * dev)1623 opvp_gen_page_info(gx_device *dev)
1624 {
1625     static char *buff = NULL;
1626     int num_copies = 1;
1627     bool landscape;
1628     char tbuff[OPVP_BUFF_SIZE];
1629 
1630     /* copies */
1631     if (!inkjet) {
1632         if (dev->IgnoreNumCopies) {
1633             num_copies = 1;
1634         } else if (dev->NumCopies_set > 0) {
1635             num_copies = dev->NumCopies;
1636         }
1637     }
1638 
1639     landscape = (dev->MediaSize[0] < dev->MediaSize[1] ? false
1640                                                        : true);
1641     memset((void*)tbuff, 0, OPVP_BUFF_SIZE);
1642     snprintf(tbuff, OPVP_BUFF_SIZE - 1,
1643        "MediaCopy=%d;DeviceResolution=deviceResolution_%s;"
1644        "MediaPageRotation=%s;MediaSize=%s",
1645        num_copies,
1646        opvp_get_sizestring(dev->x_pixels_per_inch, dev->y_pixels_per_inch),
1647        (landscape ? "landscape" : "portrait"),
1648        opvp_get_mediasize(dev));
1649 
1650     opvp_alloc_string(&buff, tbuff);
1651 
1652     return buff;
1653 }
1654 
1655 static  char *
opvp_gen_doc_info(gx_device * dev)1656 opvp_gen_doc_info(gx_device *dev)
1657 {
1658     return opvp_gen_page_info(dev);
1659 }
1660 
1661 static  char *
opvp_gen_job_info(gx_device * dev)1662 opvp_gen_job_info(gx_device *dev)
1663 {
1664     return opvp_gen_doc_info(dev);
1665 }
1666 
1667 static  int
opvp_set_brush_color(gx_device_opvp * pdev,gx_color_index color,opvp_brush_t * brush)1668 opvp_set_brush_color(gx_device_opvp *pdev, gx_color_index color,
1669     opvp_brush_t *brush)
1670 {
1671     int code;
1672     int ecode = 0;
1673     gx_color_value rgb[3];
1674 
1675     code = opvp_map_color_rgb((gx_device *)pdev, color, rgb);
1676     if (code) {
1677         ecode = -1;
1678     } else {
1679 #if ENABLE_SIMPLE_MODE
1680         brush->colorSpace = colorSpace;
1681 #else
1682         opvp_result_t           r = -1;
1683         /* call GetColorSpace */
1684         if (apiEntry->opvpGetColorSpace) {
1685             r = apiEntry->opvpGetColorSpace(printerContext,
1686                                    &(brush->colorSpace));
1687         }
1688         if (r != OPVP_OK) {
1689             brush->colorSpace = OPVP_CSPACE_DEVICEKRGB;
1690         }
1691 #endif
1692         brush->pbrush = NULL;
1693         brush->xorg = brush->yorg = 0;
1694         brush->color[3] = (color == gx_no_color_index ? -1 : 0);
1695         brush->color[2] = rgb[0];
1696         brush->color[1] = rgb[1];
1697         brush->color[0] = rgb[2];
1698     }
1699 
1700     return ecode;
1701 }
1702 
1703 static  int
opvp_draw_image(gx_device_opvp * pdev,int depth,int sw,int sh,int dw,int dh,int raster,int mask,const byte * data)1704 opvp_draw_image(
1705     gx_device_opvp *pdev,
1706     int depth,
1707     int sw,
1708     int sh,
1709     int dw,
1710     int dh,
1711     int raster,
1712     int mask,
1713     const byte *data)
1714 {
1715     opvp_result_t               r = -1;
1716     int                 ecode = 0;
1717     int                 count;
1718 
1719     /* check page-in */
1720     if (opvp_check_in_page(pdev)) return -1;
1721 
1722     /* image size */
1723     count = raster * sh;
1724 
1725     /* call DrawImage */
1726     if (apiEntry->opvpDrawImage) {
1727         r = apiEntry->opvpDrawImage(printerContext,
1728                sw,sh,
1729                raster,
1730                mask ? OPVP_IFORMAT_MASK : OPVP_IFORMAT_RAW,
1731                dw,dh,
1732                /* discard 'const' qualifier */
1733                (void *)data);
1734     }
1735     if (r != OPVP_OK) {
1736         /* call StartDrawImage */
1737         if (apiEntry->opvpStartDrawImage) {
1738             r = apiEntry->opvpStartDrawImage(printerContext,
1739                     sw,sh,
1740                     raster,
1741                     mask ? OPVP_IFORMAT_MASK : OPVP_IFORMAT_RAW,
1742                     dw,dh);
1743         }
1744         if (r == OPVP_OK) {
1745             /* call TansferDrawImage */
1746             if (apiEntry->opvpTransferDrawImage) {
1747                 r = apiEntry->opvpTransferDrawImage(
1748                        printerContext,
1749                        count,
1750                         /* discard 'const' qualifier */
1751                        (void *)data);
1752             }
1753             if (r != OPVP_OK) ecode = -1;
1754 
1755             /* call EndDrawImage */
1756             if (apiEntry->opvpEndDrawImage) {
1757                 apiEntry->opvpEndDrawImage(printerContext);
1758             }
1759         } else {
1760             ecode = 0;  /* continue... */
1761         }
1762     }
1763 
1764     return ecode;
1765 }
1766 
1767 /* ----- load/unload vector driver ----- */
1768 
1769 /*
1770  * load vector-driver
1771  */
1772 static  int
opvp_load_vector_driver(void)1773 opvp_load_vector_driver(void)
1774 {
1775     char **list = NULL;
1776     int i;
1777     void *h;
1778 
1779     if (handle) {
1780         opvp_unload_vector_driver();
1781     }
1782 
1783     if (vectorDriver) {
1784         list = opvp_gen_dynamic_lib_name();
1785     }
1786 
1787     if (list) {
1788         i = 0;
1789         while (list[i]) {
1790             if ((h = dlopen(list[i],RTLD_NOW))) {
1791                 OpenPrinter = dlsym(h,"opvpOpenPrinter");
1792                 ErrorNo = dlsym(h,"opvpErrorNo");
1793                 if (OpenPrinter && ErrorNo) {
1794                     handle = h;
1795                     break;
1796                 }
1797                 OpenPrinter = NULL;
1798                 ErrorNo = NULL;
1799                 /* try version 0.2 driver */
1800                 OpenPrinter_0_2 = dlsym(h,"OpenPrinter");
1801                 ErrorNo = dlsym(h,"errorno");
1802                 if (OpenPrinter_0_2 && ErrorNo) {
1803                     handle = h;
1804                     break;
1805                 }
1806                 OpenPrinter_0_2 = NULL;
1807                 ErrorNo = NULL;
1808             }
1809             i++;
1810         }
1811     }
1812 
1813     if (handle) {
1814         return 0;
1815     } else {
1816         return -1;
1817     }
1818 }
1819 
1820 /*
1821  * unload vector-driver
1822  */
1823 static  int
opvp_unload_vector_driver(void)1824 opvp_unload_vector_driver(void)
1825 {
1826     if (handle) {
1827         dlclose(handle);
1828         handle = NULL;
1829         OpenPrinter = NULL;
1830         ErrorNo = NULL;
1831     }
1832     return 0;
1833 }
1834 
1835 /*
1836  * prepare open
1837  */
1838 static  int
prepare_open(gx_device * dev)1839 prepare_open(gx_device *dev)
1840 {
1841     int ecode = 0;
1842     int code;
1843     opvp_result_t r = -1;
1844     opvp_api_procs_t *api_entry;
1845     int dumFD = -1;
1846     opvp_dc_t dumContext = -1;
1847     opvp_cspace_t cspace = OPVP_CSPACE_STANDARDRGB;
1848 
1849     /* open dummy device */
1850     code = open("/dev/null", O_RDWR);
1851     if (code < 0) ecode = code;
1852     else dumFD = code;
1853 
1854     /* load vector driver */
1855     if (!ecode) {
1856         if ((code = opvp_load_vector_driver())) {
1857             ecode = code;
1858         }
1859     }
1860 
1861     /* prepare array of function pointer for PDAPI */
1862     if (!ecode) {
1863         if (!apiEntry) {
1864             if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) {
1865                 ecode = -1;
1866             }
1867         } else {
1868             memset(apiEntry, 0, sizeof(opvp_api_procs_t));
1869         }
1870     }
1871 
1872     /* call opvpOpenPrinter as dummy */
1873     if (!ecode) {
1874         opvp_dc_t dc;
1875         opvp_int_t apiVersion[2];
1876 
1877         /* require version 1.0 */
1878         apiVersion[0] = 1;
1879         apiVersion[1] = 0;
1880         dc = OpenPrinterWrapper(dumFD, (opvp_char_t *)printerModel,
1881           apiVersion,&api_entry);
1882         if (dc == -1) {
1883             ecode = -1;
1884         } else {
1885             dumContext = dc;
1886         }
1887     }
1888 
1889     /* set apiEntry */
1890     if (!ecode) {
1891         nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *);
1892         memcpy(apiEntry, api_entry, nApiEntry*sizeof(void *));
1893     } else {
1894         if (apiEntry) free(apiEntry);
1895         apiEntry = NULL;
1896     }
1897 
1898     /* check vector fucntion */
1899     if (apiEntry) {
1900         if (!inkjet) {
1901             if (!(apiEntry->opvpNewPath) ||
1902                 !(apiEntry->opvpEndPath) ||
1903                 !(apiEntry->opvpStrokePath) ||
1904                 !(apiEntry->opvpSetCurrentPoint) ||
1905                 !(apiEntry->opvpLinePath) ||
1906                 !(apiEntry->opvpBezierPath)) {
1907                 /* NOT avail vector drawing mode */
1908                 vector = false;
1909             }
1910         }
1911         /* call GetColorSpace */
1912         if (apiEntry->opvpGetColorSpace) {
1913             r = apiEntry->opvpGetColorSpace(dumContext, &cspace);
1914         }
1915         if (cspace == OPVP_CSPACE_BW) {
1916             /* mono-color */
1917             colorSpace = cspace;
1918             dev->color_info.num_components = 1;
1919             dev->color_info.depth = 1;
1920             dev->color_info.max_gray = 0;
1921             dev->color_info.max_color = 0;
1922             dev->color_info.dither_grays = 1;
1923             dev->color_info.dither_colors = 1;
1924         } else if (cspace == OPVP_CSPACE_DEVICEGRAY) {
1925             /* gray-scale */
1926             colorSpace = cspace;
1927             dev->color_info.num_components = 1;
1928             dev->color_info.depth = 8;
1929             dev->color_info.max_gray = 255;
1930             dev->color_info.max_color = 255;
1931             dev->color_info.dither_grays = 256;
1932             dev->color_info.dither_colors = 256;
1933         } else {
1934             /* rgb color */
1935             colorSpace = OPVP_CSPACE_STANDARDRGB;
1936             dev->color_info.num_components = 3;
1937             dev->color_info.depth = 24;
1938             dev->color_info.max_gray = 255;
1939             dev->color_info.max_color = 255;
1940             dev->color_info.dither_grays = 256;
1941             dev->color_info.dither_colors = 256;
1942         }
1943 #if GS_VERSION_MAJOR >= 8
1944         dev->procs.get_color_mapping_procs = NULL;
1945         dev->procs.get_color_comp_index = NULL;
1946         gx_device_fill_in_procs(dev);
1947 #endif
1948     }
1949 
1950     /* call Closerinter as dummy */
1951     if (dumContext != -1) {
1952         /* call ClosePrinter */
1953         if (apiEntry->opvpClosePrinter) {
1954             apiEntry->opvpClosePrinter(dumContext);
1955         }
1956         dumContext = -1;
1957     }
1958 
1959     /* close device for dummy */
1960     if (dumFD != -1) {
1961         close(dumFD);
1962         dumFD = -1;
1963     }
1964 
1965     /* un-load vector driver */
1966     opvp_unload_vector_driver();
1967 
1968     return ecode;
1969 }
1970 
1971 /* ----- driver procs ----- */
1972 /*
1973  * open device
1974  */
1975 static  int
opvp_open(gx_device * dev)1976 opvp_open(gx_device *dev)
1977 {
1978     gx_device_opvp *pdev = (gx_device_opvp *)dev;
1979     gx_device_oprp *rdev = (gx_device_oprp *)dev;
1980     int ecode = 0;
1981     int code;
1982     opvp_result_t r = -1;
1983     opvp_dc_t dc;
1984     opvp_api_procs_t *api_entry;
1985     char *job_info = NULL;
1986     char *doc_info = NULL;
1987     char *tmp_info = NULL;
1988     float margin_width = 0;
1989     float margin_height = 0;
1990     float adj_margins[4];
1991     opvp_int_t apiVersion[2];
1992 
1993     /* prepare open : load and open as dummy */
1994     code = prepare_open(dev);
1995     if (code) {
1996         ecode = code;
1997         return ecode;
1998     }
1999 
2000     /* set margins */
2001     if (zoomAuto) {
2002         margin_width = (margins[0] + margins[2])
2003                      * dev->HWResolution[0];
2004         margin_height = (margins[1] + margins[3])
2005                       * dev->HWResolution[1];
2006         zoom[0] = (dev->width - margin_width) / dev->width;
2007         zoom[1] = (dev->height - margin_height) / dev->height;
2008         if (zoom[0] < zoom[1]) {
2009             zoom[1] = zoom[0];
2010         } else {
2011             zoom[0] = zoom[1];
2012         }
2013     }
2014     if (inkjet) {
2015         if ((margins[0] != 0) ||
2016             (margins[1] != 0) || (margins[3] != 0)) {
2017             shift[0] = margins[0] * dev->HWResolution[0];
2018             shift[1] = (margins[1] + margins[3])
2019                      * dev->HWResolution[1];
2020             zooming = true;
2021         }
2022         dev->width -= margins[2] * dev->HWResolution[0];
2023         dev->height -= margins[1] * dev->HWResolution[1];
2024     } else {
2025             if ((margins[0] != 0) || (margins[1] != 0)) {
2026                 shift[0] = margins[0] * dev->HWResolution[0];
2027                 shift[1] = margins[3] * dev->HWResolution[1];
2028                 zooming = true;
2029             }
2030             adj_margins[0] = 0;
2031             adj_margins[3] = 0;
2032             adj_margins[1] = dev->height * zoom[1] / dev->HWResolution[1]
2033                             - (dev->MediaSize[1] / PS_DPI
2034                              - (margins[1] + margins[3]));
2035             if (adj_margins[1] < 0) adj_margins[0] = 0;
2036             adj_margins[2] = dev->width * zoom[0] / dev->HWResolution[0]
2037                             - (dev->MediaSize[0] / PS_DPI
2038                              - (margins[0] + margins[2]));
2039             if (adj_margins[2] < 0) adj_margins[2] = 0;
2040             gx_device_set_margins(dev, adj_margins, true);
2041     }
2042     if ((zoom[0] != 1) || (zoom[1] != 1)) zooming = true;
2043 
2044     /* open file for output device */
2045     if (!inkjet) {
2046         pdev->v_memory = gs_memory_stable(pdev->memory);
2047         /* open output stream */
2048         code = gdev_vector_open_file_options((gx_device_vector*)dev,
2049                    512,
2050                    (VECTOR_OPEN_FILE_SEQUENTIAL
2051                    |VECTOR_OPEN_FILE_BBOX
2052                    ));
2053         if (code < 0) {
2054             ecode = code;
2055             return ecode;
2056         }
2057 #if GS_VERSION_MAJOR >= 8
2058         if (pdev->bbox_device != NULL) {
2059             if (pdev->bbox_device->memory == NULL) {
2060                 pdev->bbox_device->memory = gs_memory_stable(dev->memory);
2061             }
2062         }
2063 #endif
2064         outputFD = fileno(pdev->file);
2065     } else {
2066         /* open printer device */
2067         code = gdev_prn_open(dev);
2068         if (code < 0) {
2069             ecode = ecode;
2070             return ecode;
2071         }
2072         /* open output stream */
2073         code = gdev_prn_open_printer_seekable(dev, true, false);
2074         if (code < 0) {
2075             ecode = code;
2076             return ecode;
2077         }
2078         outputFD = fileno(rdev->file);
2079     }
2080 
2081     /* RE-load vector driver */
2082     if ((code = opvp_load_vector_driver())) {
2083         ecode = code;
2084         return ecode;
2085     }
2086 
2087     /* call opvpOpenPrinter */
2088     /* require version 1.0 */
2089     apiVersion[0] = 1;
2090     apiVersion[1] = 0;
2091     dc = OpenPrinterWrapper(outputFD,(opvp_char_t *)printerModel,
2092       apiVersion,&api_entry);
2093     if (!apiEntry) {
2094         if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) {
2095             ecode = -1;
2096         }
2097     } else {
2098         memset(apiEntry, 0, sizeof(opvp_api_procs_t));
2099     }
2100     if (dc == -1) {
2101         ecode =  -1;
2102         if (apiEntry) free(apiEntry);
2103         apiEntry = NULL;
2104         opvp_unload_vector_driver();
2105         if (inkjet) gdev_prn_close(dev);
2106         else gdev_vector_close_file((gx_device_vector *)pdev);
2107         return ecode;
2108     }
2109     printerContext = dc;
2110     nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *);
2111     memcpy(apiEntry, api_entry, nApiEntry*sizeof(void *));
2112 
2113     /* initialize */
2114     if ((!ecode) && (!inkjet)) {
2115         pdev->vec_procs = &opvp_vector_procs;
2116         if (vector) gdev_vector_init((gx_device_vector *)pdev);
2117     }
2118 
2119     if (apiEntry->opvpQueryColorSpace) {
2120         int n = sizeof(cspace_available);
2121         int nn = n;
2122         opvp_cspace_t *p = malloc(n*sizeof(opvp_cspace_t));
2123 
2124         if ((r = apiEntry->opvpQueryColorSpace(printerContext,&nn,p))
2125              == OPVP_PARAMERROR && nn > n) {
2126             /* realloc buffer and retry */
2127             p = realloc(p,nn*sizeof(opvp_cspace_t));
2128             r = apiEntry->opvpQueryColorSpace(printerContext,&nn,p);
2129         }
2130         if (r == OPVP_OK) {
2131             int i;
2132 
2133             for (i = 0;i < nn;i++) {
2134                 if (p[i] < sizeof(cspace_available)) {
2135                     cspace_available[p[i]] = 1;
2136                 }
2137             }
2138         }
2139         free(p);
2140     }
2141     /* start job */
2142     if (!ecode) {
2143         /* job info */
2144         if (jobInfo) {
2145             if (strlen(jobInfo) > 0) {
2146                 job_info = opvp_alloc_string(&job_info,jobInfo);
2147             }
2148         }
2149         tmp_info = opvp_alloc_string(&tmp_info,opvp_gen_job_info(dev));
2150         if (tmp_info) {
2151             if (strlen(tmp_info) > 0) {
2152                 if (job_info) {
2153                     if (strlen(job_info) > 0) {
2154                         opvp_cat_string(&job_info, ";");
2155                     }
2156                 }
2157                 job_info = opvp_cat_string(&job_info,OPVP_INFO_PREFIX);
2158                 job_info = opvp_cat_string(&job_info,tmp_info);
2159             }
2160         }
2161 
2162         /* call StartJob */
2163         if (apiEntry->opvpStartJob) {
2164             r = apiEntry->opvpStartJob(printerContext,
2165               (opvp_char_t *)opvp_to_utf8(job_info));
2166         }
2167         if (r != OPVP_OK) {
2168             ecode = -1;
2169         }
2170     }
2171 
2172     /* start doc */
2173     if (!ecode) {
2174         /* doc info */
2175         if (docInfo) {
2176             if (strlen(docInfo) > 0) {
2177                 doc_info = opvp_alloc_string(&doc_info,docInfo);
2178             }
2179         }
2180         tmp_info = opvp_alloc_string(&tmp_info, opvp_gen_doc_info(dev));
2181         if (tmp_info) {
2182             if (strlen(tmp_info) > 0) {
2183                 if (doc_info) {
2184                     if (strlen(doc_info) > 0) {
2185                         opvp_cat_string(&doc_info, ";");
2186                     }
2187                 }
2188                 doc_info = opvp_cat_string(&doc_info,OPVP_INFO_PREFIX);
2189                 doc_info = opvp_cat_string(&doc_info,tmp_info);
2190             }
2191         }
2192 
2193         /* call StartDoc */
2194         if (apiEntry->opvpStartDoc) {
2195             r = apiEntry->opvpStartDoc(printerContext,
2196               (opvp_char_t *)opvp_to_utf8(doc_info));
2197         }
2198         if (r != OPVP_OK) {
2199             ecode = -1;
2200         }
2201     }
2202 
2203     if (tmp_info) opvp_alloc_string(&tmp_info, NULL);
2204     if (doc_info) opvp_alloc_string(&doc_info, NULL);
2205     if (job_info) opvp_alloc_string(&job_info, NULL);
2206 
2207     return ecode;
2208 }
2209 
2210 /*
2211  * open device for inkjet
2212  */
2213 static  int
oprp_open(gx_device * dev)2214 oprp_open(gx_device *dev)
2215 {
2216     /* set inkjet mode */
2217     vector = false;
2218     inkjet = true;
2219 
2220     /* matrix */
2221     dev->procs.get_initial_matrix = opvp_get_initial_matrix;
2222     return opvp_open(dev);
2223 }
2224 
2225 /*
2226  * get initial matrix
2227  */
2228 static  void
opvp_get_initial_matrix(gx_device * dev,gs_matrix * pmat)2229 opvp_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
2230 {
2231     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2232     opvp_ctm_t omat;
2233 
2234     gx_default_get_initial_matrix(dev,pmat);
2235     if (zooming) {
2236         /* gs matrix */
2237         pmat->xx *= zoom[0];
2238         pmat->xy *= zoom[1];
2239         pmat->yx *= zoom[0];
2240         pmat->yy *= zoom[1];
2241         pmat->tx = pmat->tx * zoom[0] + shift[0];
2242         pmat->ty = pmat->ty * zoom[1] + shift[1];
2243     }
2244 
2245     if (pdev->is_open) {
2246         /* call ResetCTM */
2247         if (apiEntry->opvpResetCTM) {
2248             apiEntry->opvpResetCTM(printerContext);
2249         } else {
2250             /* call SetCTM */
2251             omat.a = 1;
2252             omat.b = 0;
2253             omat.c = 0;
2254             omat.d = 1;
2255             omat.e = 0;
2256             omat.f = 0;
2257             if (apiEntry->opvpSetCTM) {
2258                 apiEntry->opvpSetCTM(printerContext, &omat);
2259             }
2260         }
2261     }
2262 
2263     return;
2264 }
2265 
2266 /*
2267  * output page
2268  */
2269 static  int
opvp_output_page(gx_device * dev,int num_copies,int flush)2270 opvp_output_page(gx_device *dev, int num_copies, int flush)
2271 {
2272     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2273     int ecode = 0;
2274     int code = -1;
2275 
2276     if (inkjet) return gdev_prn_output_page(dev, num_copies, flush);
2277 
2278 #ifdef OPVP_IGNORE_BLANK_PAGE
2279     if (pdev->in_page) {
2280 #else
2281     /* check page-in */
2282     if (opvp_check_in_page(pdev)) return -1;
2283 #endif
2284         /* end page */
2285         code = opvp_endpage();
2286         if (code) ecode = code;
2287 
2288         pdev->in_page = false;
2289         beginPage = false;
2290 #ifdef OPVP_IGNORE_BLANK_PAGE
2291     }
2292 #endif
2293 
2294     if (vector) {
2295         gdev_vector_reset((gx_device_vector *)pdev);
2296     }
2297 
2298     code = gx_finish_output_page(dev, num_copies, flush);
2299     if (code) ecode = code;
2300 
2301     return ecode;
2302 }
2303 
2304 /*
2305  * print page
2306  */
2307 static  int
oprp_print_page(gx_device_printer * pdev,FILE * prn_stream)2308 oprp_print_page(gx_device_printer *pdev, FILE *prn_stream)
2309 {
2310     int ecode = 0;
2311     int code = -1;
2312     opvp_result_t r = -1;
2313     int raster_size;
2314     int buff_size;
2315     byte *buff = NULL;
2316     int line;
2317     int scan_lines;
2318     byte *data;
2319     int rasterWidth;
2320     bool start_page = false;
2321     bool start_raster = false;
2322 #if ENABLE_SKIP_RASTER
2323     int i;
2324     byte check;
2325 #endif
2326 
2327     /* get raster/pixel size */
2328     raster_size = gx_device_raster((gx_device *)pdev, 0);
2329     buff_size = ((raster_size + 3) >> 2) << 2;
2330     scan_lines = dev_print_scan_lines(pdev);
2331     rasterWidth = pdev->width;
2332 
2333     /* allocate buffer */
2334     buff = (byte*)calloc(1, buff_size);
2335     if (!buff) return ecode = -1;
2336 
2337     /* start page */
2338     if (!ecode) {
2339         code = opvp_startpage((gx_device *)pdev);
2340         if (code) ecode = code;
2341         else start_page = true;
2342     }
2343 
2344     /* moveto origin */
2345     if (!ecode)
2346     opvp_moveto((gx_device_vector*)pdev, 0, 0, 0, 0, 0);
2347 
2348     /* call StartRaster */
2349     if (!ecode) {
2350         if (apiEntry->opvpStartRaster) {
2351             r = apiEntry->opvpStartRaster(printerContext,rasterWidth);
2352         }
2353         if (r != OPVP_OK) {
2354             ecode = r;
2355         } else {
2356             start_raster = true;
2357         }
2358     }
2359 
2360     /* line */
2361     for (line = 0; (line < scan_lines) && (!ecode); line++) {
2362         /* get raster data */
2363         if (!ecode) {
2364             code = gdev_prn_get_bits(pdev, line, buff, &data);
2365             if (code) {
2366                 ecode = code;
2367                 break;
2368             }
2369         }
2370 #if ENABLE_SKIP_RASTER
2371         /* check support SkipRaster */
2372         if (apiEntry->opvpSkipRaster) {
2373             /* check all white */
2374             if (pdev->color_info.depth > 8) {
2375                 for (check = 0xff, i = 0; i < raster_size; i++)
2376                 {
2377                     check &= data[i];
2378                     if (check != 0xff) break;
2379                 }
2380                 /* if all white call SkipRaster */
2381                 if (check == 0xff) {
2382                     r = apiEntry->opvpSkipRaster(printerContext, 1);
2383                     if (r == OPVP_OK) continue;
2384                 }
2385             } else {
2386                 for (check = 0, i = 0; i < raster_size; i++) {
2387                     check |= data[i];
2388                     if (check) break;
2389                 }
2390                 /* if all zero call SkipRaster */
2391                 if (check) {
2392                     r = apiEntry->opvpSkipRaster(printerContext, 1);
2393                     if (r == OPVP_OK) continue;
2394                 }
2395             }
2396         }
2397 #endif
2398         /* call TransferRasterData */
2399         if (!ecode) {
2400             if (apiEntry->opvpTransferRasterData) {
2401                 r = apiEntry->opvpTransferRasterData(printerContext,
2402                                                 raster_size,
2403                                                 data);
2404             }
2405             if (r != OPVP_OK) ecode = r;
2406         }
2407     }
2408 
2409     /* call EndRaster */
2410     if (start_raster) {
2411         if (apiEntry->opvpEndRaster) {
2412             r = apiEntry->opvpEndRaster(printerContext);
2413         }
2414         if (r != OPVP_OK) ecode = r;
2415         start_raster = false;
2416     }
2417 
2418     /* end page */
2419     if (start_page) {
2420         code = opvp_endpage();
2421         if (code) ecode = code;
2422         start_page = false;
2423     }
2424 
2425     /* free buffer */
2426     if (buff) {
2427         free(buff);
2428         buff = NULL;
2429     }
2430 
2431     return ecode;
2432 }
2433 
2434 /*
2435  * close device
2436  */
2437 static  int
opvp_close(gx_device * dev)2438 opvp_close(gx_device *dev)
2439 {
2440     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2441     int ecode = 0;
2442 
2443     /* finalize */
2444     if (printerContext != -1) {
2445         /* call EndDoc */
2446         if (apiEntry->opvpEndDoc) {
2447             apiEntry->opvpEndDoc(printerContext);
2448         }
2449 
2450         /* call EndJob */
2451         if (apiEntry->opvpEndJob) {
2452             apiEntry->opvpEndJob(printerContext);
2453         }
2454 
2455         /* call ClosePrinter */
2456         if (apiEntry->opvpClosePrinter) {
2457             apiEntry->opvpClosePrinter(printerContext);
2458         }
2459         printerContext = -1;
2460     }
2461 
2462     /* unload vector driver */
2463     if (apiEntry) free(apiEntry);
2464     apiEntry = NULL;
2465     opvp_unload_vector_driver();
2466 
2467     if (inkjet) {
2468         /* close printer */
2469         gdev_prn_close(dev);
2470     } else {
2471         /* close output stream */
2472         gdev_vector_close_file((gx_device_vector *)pdev);
2473     }
2474     outputFD = -1;
2475 
2476     return ecode;
2477 }
2478 
2479 /*
2480  * map rgb color
2481  */
2482 #if GS_VERSION_MAJOR >= 8
2483 static  gx_color_index
opvp_map_rgb_color(gx_device * dev,const gx_color_value * prgb)2484 opvp_map_rgb_color(gx_device *dev,
2485         const gx_color_value *prgb /* modified for gs 8.15 */)
2486 #else
2487 static  gx_color_index
2488 opvp_map_rgb_color(gx_device *dev,
2489         gx_color_value r,
2490         gx_color_value g,
2491         gx_color_value b)
2492 #endif
2493 {
2494     opvp_cspace_t cs;
2495     uint c, m, y, k;
2496 
2497 #if !(ENABLE_SIMPLE_MODE)
2498     gx_device_opvp *pdev;
2499     opvp_result_t r;
2500 #endif
2501 
2502 #if GS_VERSION_MAJOR >= 8
2503     gx_color_value r, g, b; /* added for gs 8.15 */
2504     r = prgb[0];
2505     g = prgb[1];
2506     b = prgb[2];
2507 #endif
2508 
2509 #if !(ENABLE_SIMPLE_MODE)
2510     pdev = (gx_device_opvp *)dev;
2511     r = -1;
2512 #endif
2513     cs = OPVP_CSPACE_STANDARDRGB;
2514 
2515 #if ENABLE_SIMPLE_MODE
2516     cs = colorSpace;
2517 #else
2518     if (pdev->is_open) {
2519         /* call GetColorSpace */
2520         if (apiEntry->opvpGetColorSpace) {
2521             r = apiEntry->opvpGetColorSpace(printerContext, &cs);
2522         }
2523         if (r != OPVP_OK) {
2524             if (pdev->color_info.depth > 32) {
2525                     cs = OPVP_CSPACE_STANDARDRGB64;
2526             } else if (pdev->color_info.depth > 8 ) {
2527                     cs = OPVP_CSPACE_STANDARDRGB;
2528             } else if (pdev->color_info.depth > 1 ) {
2529                     cs = OPVP_CSPACE_DEVICEGRAY;
2530             } else {
2531                     cs = OPVP_CSPACE_BW;
2532             }
2533         }
2534     }
2535 #endif
2536 
2537     switch (cs) {
2538     case OPVP_CSPACE_STANDARDRGB64:
2539         /* unsupported */
2540         if (sizeof(gx_color_index) >= 6) {
2541             return (long long)b
2542                  + ((long long)g << 16)
2543                  + ((long long)b << 32);
2544         } else {
2545             return gx_color_value_to_byte(b)
2546                  + ((uint)gx_color_value_to_byte(g) << 8)
2547                  + ((ulong)gx_color_value_to_byte(r) << 16);
2548         }
2549         break;
2550     case OPVP_CSPACE_DEVICECMYK:
2551     case OPVP_CSPACE_DEVICECMY:
2552         /* unsupported */
2553         c = gx_color_value_to_byte(~r);
2554         m = gx_color_value_to_byte(~g);
2555         y = gx_color_value_to_byte(~b);
2556         if (cs == OPVP_CSPACE_DEVICECMYK) {
2557             k = (c<m ? (c<y ? c : y) : (m<y ? m : y));
2558             c -= k;
2559             m -= k;
2560             y -= k;
2561         } else {
2562             k = 0;
2563         }
2564         return (k + (y << 8) + (m << 16) + (c << 24));
2565         break;
2566     case OPVP_CSPACE_DEVICEGRAY:
2567 #if GS_VERSION_MAJOR >= 8
2568         {
2569             gx_color_value rgb[3];
2570             rgb[0] = rgb[1] = rgb[2] = r;
2571             return gx_default_gray_map_rgb_color(dev, rgb);
2572         }
2573 #else
2574         return gx_default_gray_map_rgb_color(dev, r, g, b);
2575 #endif
2576         break;
2577     case OPVP_CSPACE_BW :
2578 #if GS_VERSION_MAJOR >= 8
2579         return gx_default_b_w_map_rgb_color(dev, prgb);
2580 #else
2581         return gx_default_b_w_map_rgb_color(dev, r, g, b);
2582 #endif
2583         break;
2584     case OPVP_CSPACE_STANDARDRGB:
2585     case OPVP_CSPACE_DEVICEKRGB:
2586     default:
2587 #if GS_VERSION_MAJOR >= 8
2588         return gx_default_rgb_map_rgb_color(dev, prgb);
2589 #else
2590         return gx_default_rgb_map_rgb_color(dev, r, g, b);
2591 #endif
2592         break;
2593     }
2594 }
2595 
2596 /*
2597  * map color rgb
2598  */
2599 static  int
opvp_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])2600 opvp_map_color_rgb(gx_device *dev, gx_color_index color,
2601     gx_color_value prgb[3])
2602 {
2603 #if !(ENABLE_SIMPLE_MODE)
2604     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2605     opvp_result_t r = -1;
2606 #endif
2607     opvp_cspace_t cs = OPVP_CSPACE_STANDARDRGB;
2608     uint c, m, y, k;
2609 
2610 #if ENABLE_SIMPLE_MODE
2611     cs = colorSpace;
2612 #else
2613     /* call GetColorSpace */
2614     if (pdev->is_open) {
2615         if (apiEntry->opvpGetColorSpace) {
2616             r = apiEntry->opvpGetColorSpace(printerContext, &cs);
2617         }
2618         if (r != OPVP_OK) {
2619             if (pdev->color_info.depth > 32) {
2620                 cs = OPVP_CSPACE_STANDARDRGB64;
2621             } else if (pdev->color_info.depth > 8 ) {
2622                 cs = OPVP_CSPACE_STANDARDRGB;
2623             } else if (pdev->color_info.depth > 1 ) {
2624                 cs = OPVP_CSPACE_DEVICEGRAY;
2625             } else {
2626                 cs = OPVP_CSPACE_BW;
2627             }
2628         }
2629     }
2630 #endif
2631 
2632     switch (cs) {
2633     case OPVP_CSPACE_STANDARDRGB64:
2634         /* unsupported */
2635         if (sizeof(gx_color_index) >= 6) {
2636             prgb[0] = ((long long)color >> 32) & 0xffff;
2637             prgb[1] = ((long long)color >> 16) & 0xffff;
2638             prgb[2] = color & 0xffff;
2639         } else {
2640             prgb[0] = gx_color_value_from_byte((color >> 16) & 0xff);
2641             prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
2642             prgb[2] = gx_color_value_from_byte(color & 0xff);
2643         }
2644         break;
2645     case OPVP_CSPACE_DEVICECMYK:
2646     case OPVP_CSPACE_DEVICECMY:
2647         /* unsupported */
2648         c = gx_color_value_from_byte((color >> 24) & 0xff);
2649         m = gx_color_value_from_byte((color >> 16) & 0xff);
2650         y = gx_color_value_from_byte((color >> 8) & 0xff);
2651         if (cs == OPVP_CSPACE_DEVICECMYK) {
2652             k = gx_color_value_from_byte(color & 0xff);
2653             c += k; if (c > 255) c = 255;
2654             m += k; if (m > 255) m = 255;
2655             y += k; if (y > 255) y = 255;
2656         }
2657         prgb[0] = gx_color_value_from_byte(~c & 0xff);
2658         prgb[1] = gx_color_value_from_byte(~m & 0xff);
2659         prgb[2] = gx_color_value_from_byte(~y & 0xff);
2660         break;
2661     case OPVP_CSPACE_DEVICEGRAY:
2662         return gx_default_gray_map_color_rgb(dev, color, prgb);
2663         break;
2664     case OPVP_CSPACE_BW:
2665         return gx_default_b_w_map_color_rgb(dev, color, prgb);
2666         break;
2667     case OPVP_CSPACE_STANDARDRGB:
2668     case OPVP_CSPACE_DEVICEKRGB:
2669     default:
2670         return gx_default_rgb_map_color_rgb(dev, color, prgb);
2671         break;
2672     }
2673 
2674     return 0;
2675 }
2676 
2677 /*
2678  * fill rectangle
2679  */
2680 static  int
opvp_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)2681 opvp_fill_rectangle(
2682     gx_device *dev,
2683     int x,
2684     int y,
2685     int w,
2686     int h,
2687     gx_color_index color)
2688 {
2689     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2690     byte data[8] = {0xC0, 0, 0, 0, 0xC0, 0, 0, 0};
2691     int code = -1;
2692     int ecode = 0;
2693     opvp_brush_t brush;
2694     opvp_point_t point;
2695 
2696     if (vector) {
2697         return gdev_vector_fill_rectangle( dev, x, y, w, h, color);
2698     }
2699 
2700     /* check page-in */
2701     if (opvp_check_in_page(pdev)) return -1;
2702 
2703 #if !(ENABLE_SIMPLE_MODE)
2704     /* call SaveGS */
2705     if (apiEntry->opvpSaveGS) {
2706         apiEntry->opvpSaveGS(printerContext);
2707     }
2708 #endif
2709 
2710     /* one-color */
2711     opvp_set_brush_color(pdev, color, &brush);
2712 
2713     /* call SetFillColor */
2714     if (apiEntry->opvpSetFillColor) {
2715         apiEntry->opvpSetFillColor(printerContext, &brush);
2716     }
2717 
2718     /* call SetCurrentPoint */
2719     OPVP_I2FIX(x, point.x);
2720     OPVP_I2FIX(y, point.y);
2721     if (apiEntry->opvpSetCurrentPoint) {
2722         apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y);
2723     }
2724 
2725     /* draw image */
2726     code = opvp_draw_image(pdev,
2727                            1,
2728                            2, 2,
2729                            w, h,
2730                            4,
2731                            0,
2732                            data);
2733     if (code) {
2734         ecode = code;
2735     }
2736 
2737     /* restore fill color */
2738     if (vectorFillColor) {
2739         /* call SetFillColor */
2740         if (apiEntry->opvpSetFillColor) {
2741             apiEntry->opvpSetFillColor(printerContext,vectorFillColor);
2742         }
2743     }
2744 
2745 #if !(ENABLE_SIMPLE_MODE)
2746     /* call RestoreGS */
2747     if (apiEntry->opvpRestoreGS) {
2748         apiEntry->opvpRestoreGS(printerContext);
2749     }
2750 #endif
2751 
2752     return ecode;
2753 }
2754 
2755 /*
2756  * copy mono
2757  */
2758 static  int
opvp_copy_mono(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)2759 opvp_copy_mono(
2760     gx_device *dev,
2761     const byte *data,
2762     int data_x,
2763     int raster,
2764     gx_bitmap_id id,
2765     int x,
2766     int y,
2767     int w,
2768     int h,
2769     gx_color_index zero,
2770     gx_color_index one)
2771 {
2772     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2773     int code = -1;
2774     int ecode = 0;
2775     opvp_brush_t brush;
2776     opvp_point_t point;
2777     const byte *buff = data;
2778     byte *mybuf = NULL;
2779     int i, j;
2780     byte *d;
2781     const byte *s;
2782     int byte_offset = 0;
2783     int byte_length = raster;
2784     int bit_shift = 0;
2785     int adj_raster = raster;
2786     unsigned char bit_mask = 0xff;
2787     bool reverse = false;
2788 
2789     /* check page-in */
2790     if (opvp_check_in_page(pdev)) return -1;
2791 
2792     /* data offset */
2793     if (data_x) {
2794         byte_offset = data_x >> 3;
2795         bit_shift = data_x & 0x07;
2796         if (bit_shift) bit_mask <<= (8 - bit_shift);
2797 
2798         byte_length = ((w + 7) >> 3);
2799         adj_raster = ((byte_length + 3) >> 2) << 2;
2800 
2801         buff = mybuf = calloc(adj_raster, h);
2802         if (!mybuf) {
2803             /* memory error */
2804             return -1;
2805         }
2806         s = &(data[byte_offset]);
2807         d = mybuf;
2808         if (bit_shift) {
2809             for (i = 0;i < h; i++, d += adj_raster, s+= raster) {
2810                 for (j = 0; j < byte_length; j++) {
2811                     d[j] = ((s[j] & ~bit_mask) << bit_shift)
2812                          | ((s[j + 1] & bit_mask) >> (8 - bit_shift));
2813                 }
2814             }
2815         } else {
2816             for (i = 0;i < h; i++, d += adj_raster, s+= raster) {
2817                 for (j = 0; j < byte_length; j++) {
2818                     d[j] = s[j];
2819                 }
2820             }
2821         }
2822         byte_offset = 0;
2823     }
2824 
2825 #if !(ENABLE_SIMPLE_MODE)
2826     /* call SaveGS */
2827     if (apiEntry->opvpSaveGS) {
2828         apiEntry->opvpSaveGS(printerContext);
2829     }
2830 #endif
2831     if (one == gx_no_color_index) {
2832         gx_color_index tc;
2833 
2834         reverse = (!reverse);
2835         tc = zero;
2836         zero = one;
2837         one = tc;
2838     }
2839 
2840     if (zero != gx_no_color_index) {
2841         /* not mask */
2842         /* Set PaintMode */
2843         if (apiEntry->opvpSetPaintMode) {
2844             apiEntry->opvpSetPaintMode(printerContext,OPVP_PAINTMODE_OPAQUE);
2845         }
2846         /* zero-color */
2847         opvp_set_brush_color(pdev, zero, &brush);
2848 
2849         /* call SetBgColor */
2850         if (apiEntry->opvpSetBgColor) {
2851             apiEntry->opvpSetBgColor(printerContext, &brush);
2852         }
2853     }
2854 
2855     /* one-color */
2856     opvp_set_brush_color(pdev, one, &brush);
2857 
2858     /* call SetFillColor */
2859     if (apiEntry->opvpSetFillColor) {
2860         apiEntry->opvpSetFillColor(printerContext, &brush);
2861     }
2862 
2863     if (reverse) {
2864         /* 0/1 reverse image */
2865         int n = adj_raster*h;
2866 
2867         if (buff == data) {
2868             /* buff was not allocated from this function yet */
2869             /* allocate here */
2870             if ((mybuf = malloc(n)) == 0) return -1;
2871         }
2872         for (i = 0;i < n;i++) {
2873             mybuf[i] = ~buff[i];
2874         }
2875         buff = mybuf;
2876     }
2877     /* call SetCurrentPoint */
2878     OPVP_I2FIX(x, point.x);
2879     OPVP_I2FIX(y, point.y);
2880     if (apiEntry->opvpSetCurrentPoint) {
2881         apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y);
2882     }
2883 
2884     /* draw image */
2885     code = opvp_draw_image(pdev,
2886                            1,
2887                            w, h,
2888                            w, h,
2889                            adj_raster,
2890                            1,
2891                            &(buff[byte_offset]));
2892     if (code) {
2893         ecode = code;
2894     }
2895 
2896     if (zero != gx_no_color_index) {
2897         /* restore PaintMode */
2898         if (apiEntry->opvpSetPaintMode) {
2899             apiEntry->opvpSetPaintMode(printerContext,
2900               OPVP_PAINTMODE_TRANSPARENT);
2901         }
2902     }
2903     /* restore fill color */
2904     if (vectorFillColor) {
2905         /* call SetFillColor */
2906         if (apiEntry->opvpSetFillColor) {
2907             apiEntry->opvpSetFillColor(printerContext,vectorFillColor);
2908         }
2909     }
2910 
2911 #if !(ENABLE_SIMPLE_MODE)
2912     /* call RestoreGS */
2913     if (apiEntry->opvpRestoreGS) {
2914         apiEntry->opvpRestoreGS(printerContext);
2915     }
2916 #endif
2917 
2918     if (buff != data) {
2919         /* buff was allocated from this function */
2920         if (mybuf) free(mybuf);
2921     }
2922 
2923     return ecode;
2924 }
2925 
2926 /*
2927  * copy color
2928  */
2929 static  int
opvp_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h)2930 opvp_copy_color(
2931     gx_device *dev,
2932     const byte *data,
2933     int data_x,
2934     int raster,
2935     gx_bitmap_id id,
2936     int x,
2937     int y,
2938     int w,
2939     int h)
2940 {
2941     gx_device_opvp *pdev = (gx_device_opvp *)dev;
2942     int code = -1;
2943     int ecode = 0;
2944     opvp_point_t point;
2945     const byte *buff = data;
2946     byte *mybuf = NULL;
2947     int i;
2948     byte *d;
2949     const byte *s;
2950     int byte_length = raster;
2951     int depth;
2952     int pixel;
2953     int adj_raster = raster;
2954 
2955     /* check page-in */
2956     if (opvp_check_in_page(pdev)) return -1;
2957 
2958     /* data offset */
2959     if (data_x) {
2960         depth = pdev->color_info.depth;
2961         pixel = (depth + 7) >> 3;
2962         byte_length = pixel * w;
2963         adj_raster = ((byte_length + 3) >> 2) << 2;
2964 
2965         buff = mybuf = malloc(adj_raster * h);
2966         if (!mybuf) {
2967             /* memory error */
2968             return -1;
2969         }
2970         s = &(data[data_x*pixel]);
2971         d = mybuf;
2972         for (i = 0;i < h; i++, d += adj_raster, s += raster) {
2973             memcpy(d, s, byte_length);
2974         }
2975         data_x = 0;
2976     }
2977 
2978 #if !(ENABLE_SIMPLE_MODE)
2979     /* call SaveGS */
2980     if (apiEntry->opvpSaveGS) {
2981         apiEntry->opvpSaveGS(printerContext);
2982     }
2983 #endif
2984 
2985     /* call SetCurrentPoint */
2986     OPVP_I2FIX(x, point.x);
2987     OPVP_I2FIX(y, point.y);
2988     if (apiEntry->opvpSetCurrentPoint) {
2989         apiEntry->opvpSetCurrentPoint(printerContext, point.x, point.y);
2990     }
2991 
2992     /* draw image */
2993     code = opvp_draw_image(pdev,
2994                            pdev->color_info.depth,
2995                            w, h,
2996                            w, h,
2997                            adj_raster,
2998                            0,
2999                            &(buff[data_x]));
3000     if (code) {
3001         ecode = code;
3002     }
3003 
3004 #if !(ENABLE_SIMPLE_MODE)
3005     /* call RestoreGS */
3006     if (apiEntry->opvpRestoreGS) {
3007         apiEntry->opvpRestoreGS(printerContext);
3008     }
3009 #endif
3010 
3011     if (buff != data) {
3012         /* buff was allocated from this function */
3013         if (mybuf) free(mybuf);
3014     }
3015 
3016     return ecode;
3017 }
3018 
3019 /*
3020  * get params
3021  */
3022 static  int
_get_params(gs_param_list * plist)3023 _get_params(gs_param_list *plist)
3024 {
3025     int code;
3026     int ecode = 0;
3027     gs_param_name pname;
3028     gs_param_string vdps;
3029     gs_param_string pmps;
3030     gs_param_string jips;
3031     gs_param_string dips;
3032     gs_param_string fips;
3033     gs_param_string mlps;
3034     gs_param_string mtps;
3035     gs_param_string mrps;
3036     gs_param_string mbps;
3037     gs_param_string zmps;
3038     char buff[OPVP_BUFF_SIZE];
3039 
3040     /* get params */
3041 
3042     /* vector driver name */
3043     pname = "Driver";
3044     vdps.data = (byte *)vectorDriver;
3045     vdps.size = (vectorDriver ? strlen(vectorDriver) + 1 : 0);
3046     vdps.persistent = false;
3047     code = param_write_string(plist, pname, &vdps);
3048     if (code) ecode = code;
3049 
3050     /* printer model name */
3051     pname = "Model";
3052     pmps.data = (byte *)printerModel;
3053     pmps.size = (printerModel ? strlen(printerModel) + 1 : 0);
3054     pmps.persistent = false;
3055     code = param_write_string(plist, pname, &pmps);
3056     if (code) ecode = code;
3057 
3058     /* job info */
3059     pname = "JobInfo";
3060     jips.data = (byte *)jobInfo;
3061     jips.size = (jobInfo ? strlen(jobInfo) + 1 : 0);
3062     jips.persistent = false;
3063     code = param_write_string(plist, pname, &jips);
3064     if (code) ecode = code;
3065 
3066     /* doc info */
3067     pname = "DocInfo";
3068     dips.data = (byte *)docInfo;
3069     dips.size = (docInfo ? strlen(docInfo) + 1 : 0);
3070     dips.persistent = false;
3071     code = param_write_string(plist, pname, &dips);
3072     if (code) ecode = code;
3073 
3074     /* fast image support */
3075     switch (FastImageMode) {
3076     case FastImageNoCTM:
3077         opvp_alloc_string(&fastImage, "NoCTM");
3078         break;
3079     case FastImageNoRotate:
3080         opvp_alloc_string(&fastImage, "NoRotateCTM");
3081         break;
3082     case FastImageRightAngle:
3083         opvp_alloc_string(&fastImage, "RightAngleCTM");
3084         break;
3085     case FastImageReverseAngle:
3086         opvp_alloc_string(&fastImage, "ReverseAngleCTM");
3087         break;
3088     case FastImageAll:
3089         opvp_alloc_string(&fastImage, "All");
3090         break;
3091     case FastImageDisable:
3092     default:
3093         opvp_alloc_string(&fastImage, NULL);
3094         break;
3095     }
3096     pname = "FastImage";
3097     fips.data = (byte *)fastImage;
3098     fips.size = (fastImage ? strlen(fastImage) + 1 : 0);
3099     fips.persistent = false;
3100     code = param_write_string(plist, pname, &fips);
3101     if (code) ecode = code;
3102 
3103     /* margins */
3104     memset((void*)buff, 0, OPVP_BUFF_SIZE);
3105     pname = "MarginLeft";
3106     snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[0]);
3107     mlps.data = (byte *)buff;
3108     mlps.size = strlen(buff) + 1;
3109     mlps.persistent = false;
3110     code = param_write_string(plist, pname, &mlps);
3111     if (code) ecode = code;
3112     pname = "MarginTop";
3113     snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[3]);
3114     mtps.data = (byte *)buff;
3115     mtps.size = strlen(buff) + 1;
3116     mtps.persistent = false;
3117     code = param_write_string(plist, pname, &mtps);
3118     if (code) ecode = code;
3119     pname = "MarginRight";
3120     snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[2]);
3121     mrps.data = (byte *)buff;
3122     mrps.size = strlen(buff) + 1;
3123     mrps.persistent = false;
3124     code = param_write_string(plist, pname, &mrps);
3125     if (code) ecode = code;
3126     pname = "MarginBottom";
3127     snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[1]);
3128     mbps.data = (byte *)buff;
3129     mbps.size = strlen(buff) + 1;
3130     mbps.persistent = false;
3131     code = param_write_string(plist, pname, &mbps);
3132     if (code) ecode = code;
3133 
3134     /* zoom */
3135     pname = "Zoom";
3136     snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",zoom[0]);
3137     zmps.data = (byte *)buff;
3138     zmps.size = strlen(buff) + 1;
3139     zmps.persistent = false;
3140     code = param_write_string(plist, pname, &zmps);
3141     if (code) ecode = code;
3142 
3143     return ecode;
3144 }
3145 
3146 /*
3147  * get params for vector
3148  */
3149 static  int
opvp_get_params(gx_device * dev,gs_param_list * plist)3150 opvp_get_params(gx_device *dev, gs_param_list *plist)
3151 {
3152     int code;
3153 
3154     /* get default params */
3155     code = gdev_vector_get_params(dev, plist);
3156     if (code) return code;
3157 
3158     /* get params */
3159     return _get_params(plist);
3160 }
3161 
3162 /*
3163  * get params for inkjet
3164  */
3165 static  int
oprp_get_params(gx_device * dev,gs_param_list * plist)3166 oprp_get_params(gx_device *dev, gs_param_list *plist)
3167 {
3168     int code;
3169 
3170     /* get default params */
3171     code = gdev_prn_get_params(dev, plist);
3172     if (code) return code;
3173 
3174     /* get params */
3175     return _get_params(plist);
3176 }
3177 
3178 /*
3179  * put params
3180  */
3181 static  int
_put_params(gs_param_list * plist)3182 _put_params(gs_param_list *plist)
3183 {
3184     int code;
3185     int ecode = 0;
3186     gs_param_name pname;
3187     char *buff = NULL;
3188     gs_param_string vdps;
3189     gs_param_string pmps;
3190     gs_param_string jips;
3191     gs_param_string dips;
3192     gs_param_string fips;
3193     gs_param_string mlps;
3194     gs_param_string mtps;
3195     gs_param_string mrps;
3196     gs_param_string mbps;
3197     gs_param_string zmps;
3198 
3199     /* vector driver name */
3200     pname = "Driver";
3201     code = param_read_string(plist, pname, &vdps);
3202     switch (code) {
3203     case 0:
3204         buff = realloc(buff, vdps.size + 1);
3205         memcpy(buff, vdps.data, vdps.size);
3206         buff[vdps.size] = 0;
3207         opvp_alloc_string(&vectorDriver, buff);
3208         break;
3209     case 1:
3210         /* opvp_alloc_string(&vectorDriver, NULL);*/
3211         break;
3212     default:
3213         ecode = code;
3214         param_signal_error(plist, pname, ecode);
3215     }
3216 
3217     /* printer model name */
3218     pname = "Model";
3219     code = param_read_string(plist, pname, &pmps);
3220     switch (code) {
3221     case 0:
3222         buff = realloc(buff, pmps.size + 1);
3223         memcpy(buff, pmps.data, pmps.size);
3224         buff[pmps.size] = 0;
3225         opvp_alloc_string(&printerModel, buff);
3226         break;
3227     case 1:
3228         /*opvp_alloc_string(&printerModel, NULL);*/
3229         break;
3230     default:
3231         ecode = code;
3232         param_signal_error(plist, pname, ecode);
3233     }
3234 
3235     /* job info */
3236     pname = "JobInfo";
3237     code = param_read_string(plist, pname, &jips);
3238     switch (code) {
3239     case 0:
3240         buff = realloc(buff, jips.size + 1);
3241         memcpy(buff, jips.data, jips.size);
3242         buff[jips.size] = 0;
3243         opvp_alloc_string(&jobInfo, buff);
3244         break;
3245     case 1:
3246         /*opvp_alloc_string(&jobInfo, NULL);*/
3247         break;
3248     default:
3249         ecode = code;
3250         param_signal_error(plist, pname, ecode);
3251     }
3252 
3253     /* doc info */
3254     pname = "DocInfo";
3255     code = param_read_string(plist, pname, &dips);
3256     switch (code) {
3257     case 0:
3258         buff = realloc(buff, dips.size + 1);
3259         memcpy(buff, dips.data, dips.size);
3260         buff[dips.size] = 0;
3261         opvp_alloc_string(&docInfo, buff);
3262         break;
3263     case 1:
3264         /*opvp_alloc_string(&docInfo, NULL);*/
3265         break;
3266     default:
3267         ecode = code;
3268         param_signal_error(plist, pname, ecode);
3269     }
3270 
3271     /* fast image support */
3272     pname = "FastImage";
3273     code = param_read_string(plist, pname, &fips);
3274     switch (code) {
3275     case 0:
3276         buff = realloc(buff, fips.size + 1);
3277         memcpy(buff, fips.data, fips.size);
3278         buff[fips.size] = 0;
3279         opvp_alloc_string(&fastImage, buff);
3280         if (strcasecmp(fastImage,"NoCTM")==0) {
3281             FastImageMode = FastImageNoCTM;
3282         } else if (strncasecmp(fastImage,"NoRotate",8)==0) {
3283             FastImageMode = FastImageNoRotate;
3284         } else if (strncasecmp(fastImage,"Right",5)==0) {
3285             FastImageMode = FastImageRightAngle;
3286         } else if (strncasecmp(fastImage,"Reverse",7)==0) {
3287             FastImageMode = FastImageReverseAngle;
3288         } else if (strncasecmp(fastImage,"All",3)==0) {
3289             FastImageMode = FastImageAll;
3290         } else {
3291             FastImageMode = FastImageDisable;
3292         }
3293         break;
3294     case 1:
3295         /*opvp_alloc_string(&fastImage, NULL);*/
3296         break;
3297     default:
3298         ecode = code;
3299         param_signal_error(plist, pname, ecode);
3300     }
3301 
3302     /* margins */
3303     pname = "MarginLeft";
3304     code = param_read_string(plist, pname, &mlps);
3305     switch (code) {
3306     case 0:
3307         buff = realloc(buff, mlps.size + 1);
3308         memcpy(buff, mlps.data, mlps.size);
3309         buff[mlps.size] = 0;
3310         margins[0] = atof(buff);
3311         break;
3312     case 1:
3313         break;
3314     default:
3315         ecode = code;
3316         param_signal_error(plist, pname, ecode);
3317     }
3318     pname = "MarginTop";
3319     code = param_read_string(plist, pname, &mtps);
3320     switch (code) {
3321     case 0:
3322         buff = realloc(buff, mtps.size + 1);
3323         memcpy(buff, mtps.data, mtps.size);
3324         buff[mtps.size] = 0;
3325         margins[3] = atof(buff);
3326         break;
3327     case 1:
3328         break;
3329     default:
3330         ecode = code;
3331         param_signal_error(plist, pname, ecode);
3332     }
3333     pname = "MarginRight";
3334     code = param_read_string(plist, pname, &mrps);
3335     switch (code) {
3336     case 0:
3337         buff = realloc(buff, mrps.size + 1);
3338         memcpy(buff, mrps.data, mrps.size);
3339         buff[mrps.size] = 0;
3340         margins[2] = atof(buff);
3341         break;
3342     case 1:
3343         break;
3344     default:
3345         ecode = code;
3346         param_signal_error(plist, pname, ecode);
3347     }
3348     pname = "MarginBottom";
3349     code = param_read_string(plist, pname, &mbps);
3350     switch (code) {
3351     case 0:
3352         buff = realloc(buff, mbps.size + 1);
3353         memcpy(buff, mbps.data, mbps.size);
3354         buff[mbps.size] = 0;
3355         margins[1] = atof(buff);
3356         break;
3357     case 1:
3358         break;
3359     default:
3360         ecode = code;
3361         param_signal_error(plist, pname, ecode);
3362     }
3363 
3364     /* zoom */
3365     pname = "Zoom";
3366     code = param_read_string(plist, pname, &zmps);
3367     switch (code) {
3368     case 0:
3369         buff = realloc(buff, zmps.size + 1);
3370         memcpy(buff, zmps.data, zmps.size);
3371         buff[zmps.size] = 0;
3372         if (strncasecmp(buff, "Auto", 4)) {
3373             zoom[0] = atof(buff);
3374             if (zoom[0] > 0) {
3375                 zoom[1] = zoom[0];
3376             } else {
3377                 zoom[0] = zoom[1] = 1;
3378             }
3379         } else {
3380             zoom[0] = zoom[1] = 1;
3381             zoomAuto = true;
3382         }
3383         break;
3384     case 1:
3385         break;
3386     default:
3387         ecode = code;
3388         param_signal_error(plist, pname, ecode);
3389     }
3390 
3391     if (buff) free(buff);
3392 
3393     return ecode;
3394 }
3395 
3396 /*
3397  * put params for vector
3398  */
3399 static  int
opvp_put_params(gx_device * dev,gs_param_list * plist)3400 opvp_put_params(gx_device *dev, gs_param_list *plist)
3401 {
3402     int code;
3403 
3404     /* put params */
3405     code = _put_params(plist);
3406     if (code) return code;
3407 
3408     /* put default params */
3409     return gdev_vector_put_params(dev, plist);
3410 }
3411 
3412 /*
3413  * put params for inkjet
3414  */
3415 static  int
oprp_put_params(gx_device * dev,gs_param_list * plist)3416 oprp_put_params(gx_device *dev, gs_param_list *plist)
3417 {
3418     int code;
3419 
3420     /* put params */
3421     code = _put_params(plist);
3422     if (code) return code;
3423 
3424     /* put default params */
3425     return gdev_prn_put_params(dev, plist);
3426 }
3427 
checkPath(const gx_path * ppath)3428 static int checkPath(const gx_path *ppath)
3429 {
3430     unsigned int npoints = 0;
3431     fixed vs[6];
3432     int op;
3433     gs_path_enum path;
3434 
3435     gx_path_enum_init(&path, ppath);
3436 
3437     while ((op = gx_path_enum_next(&path, (gs_fixed_point *)vs)) != 0) {
3438         switch (op) {
3439         case gs_pe_lineto:
3440         case gs_pe_moveto:
3441             npoints += 1;
3442             break;
3443         case gs_pe_curveto:
3444             npoints += 3;
3445             break;
3446         case gs_pe_closepath:
3447             break;
3448         default:
3449             break;
3450         }
3451         if (npoints > MAX_PATH_POINTS) {
3452             return 0;
3453         }
3454 
3455     }
3456     return 1;
3457 }
3458 
checkCPath(const gx_clip_path * pcpath)3459 static int checkCPath(const gx_clip_path *pcpath)
3460 {
3461     const gx_clip_list *list;
3462     const gx_clip_rect *prect;
3463     int npoints;
3464 
3465     if (pcpath == 0) return 1;
3466     if (pcpath->path_valid) {
3467         return checkPath(&pcpath->path);
3468     }
3469     list = gx_cpath_list(pcpath);
3470     prect = list->head;
3471     if (prect == 0) {
3472         prect = &list->single;
3473     }
3474     npoints = 0;
3475     for (;prect != 0;prect = prect->next) {
3476         npoints += 4;
3477         if (npoints > MAX_PATH_POINTS) {
3478             return 0;
3479         }
3480     }
3481     return 1;
3482 }
3483 
3484 /*
3485  * fill path
3486  */
3487 static  int
opvp_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_device_color * pdevc,const gx_clip_path * pxpath)3488 opvp_fill_path(
3489     gx_device *dev,
3490     const gs_imager_state *pis,
3491     gx_path *ppath,
3492     const gx_fill_params *params,
3493     const gx_device_color *pdevc,
3494     const gx_clip_path *pxpath)
3495 {
3496     bool draw_image = false;
3497     gs_fixed_rect inner, outer;
3498 
3499     /* check if paths are too complex */
3500     if (!checkPath(ppath) || !checkCPath(pxpath)) {
3501         return gx_default_fill_path(dev, pis, ppath, params, pdevc, pxpath);
3502     }
3503     /* check clippath support */
3504     if (!(apiEntry->opvpSetClipPath)) {
3505         /* get clipping box area */
3506         gx_cpath_inner_box(pxpath,&inner);
3507         gx_cpath_outer_box(pxpath,&outer);
3508         /* check difference between inner-box and outer-box */
3509         if ((inner.p.x != outer.p.x) || (inner.p.y != outer.p.y) ||
3510             (inner.q.x != outer.q.x) || (inner.q.y != outer.q.y)) {
3511             /* set draw by image */
3512             draw_image = true;
3513         }
3514     }
3515 
3516     if (!vector || draw_image) {
3517         return gx_default_fill_path(dev, pis, ppath, params, pdevc, pxpath);
3518     }
3519 
3520     return gdev_vector_fill_path(dev, pis, ppath, params, pdevc, pxpath);
3521 }
3522 
3523 /*
3524  * stroke path
3525  */
3526 static  int
opvp_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pxpath)3527 opvp_stroke_path(
3528     gx_device *dev,
3529     const gs_imager_state *pis,
3530     gx_path *ppath,
3531     const gx_stroke_params *params,
3532     const gx_drawing_color *pdcolor,
3533     const gx_clip_path *pxpath)
3534 {
3535     bool draw_image = false;
3536     gs_fixed_rect inner, outer;
3537 
3538     /* check if paths are too complex */
3539     if (!checkPath(ppath) || !checkCPath(pxpath)) {
3540         return gx_default_stroke_path(dev, pis, ppath,
3541                                       params, pdcolor, pxpath);
3542     }
3543     /* check clippath support */
3544     if (!(apiEntry->opvpSetClipPath)) {
3545         /* get clipping box area */
3546         gx_cpath_inner_box(pxpath,&inner);
3547         gx_cpath_outer_box(pxpath,&outer);
3548         /* check difference between inner-box and outer-box */
3549         if ((inner.p.x != outer.p.x) || (inner.p.y != outer.p.y) ||
3550             (inner.q.x != outer.q.x) || (inner.q.y != outer.q.y)) {
3551             /* set draw by image */
3552             draw_image = true;
3553         }
3554     }
3555 
3556     if (!vector || draw_image) {
3557         return gx_default_stroke_path(dev, pis, ppath,
3558                                       params, pdcolor, pxpath);
3559     }
3560 
3561     return gdev_vector_stroke_path(dev, pis, ppath,
3562                                    params, pdcolor, pxpath);
3563 }
3564 
3565 /*
3566  * fill mask
3567  */
3568 static  int
opvp_fill_mask(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)3569 opvp_fill_mask(
3570     gx_device *dev,
3571     const byte *data,
3572     int data_x,
3573     int raster,
3574     gx_bitmap_id id,
3575     int x,
3576     int y,
3577     int w,
3578     int h,
3579     const gx_drawing_color *pdcolor,
3580     int depth,
3581     gs_logical_operation_t lop,
3582     const gx_clip_path *pcpath)
3583 {
3584     if (vector) {
3585 #if GS_VERSION_MAJOR >= 8       /* for gs 8.15 */
3586         gdev_vector_update_fill_color((gx_device_vector *)dev, NULL, pdcolor);
3587 #else
3588         gdev_vector_update_fill_color((gx_device_vector *)dev, pdcolor);
3589 #endif
3590         gdev_vector_update_clip_path((gx_device_vector *)dev, pcpath);
3591         gdev_vector_update_log_op((gx_device_vector *)dev, lop);
3592     }
3593 
3594     return gx_default_fill_mask(dev, data, data_x, raster, id,
3595                                 x, y, w, h, pdcolor, depth, lop, pcpath);
3596 }
3597 
3598 /*
3599  * begin image
3600  */
3601 static  int
opvp_begin_image(gx_device * dev,const gs_imager_state * pis,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)3602 opvp_begin_image(
3603     gx_device *dev,
3604     const gs_imager_state *pis,
3605     const gs_image_t *pim,
3606     gs_image_format_t format,
3607     const gs_int_rect *prect,
3608     const gx_drawing_color *pdcolor,
3609     const gx_clip_path *pcpath,
3610     gs_memory_t  *mem,
3611     gx_image_enum_common_t **pinfo)
3612 {
3613     gx_device_vector *vdev =(gx_device_vector *)dev;
3614     gdev_vector_image_enum_t *vinfo;
3615     gs_matrix mtx;
3616     opvp_ctm_t ctm;
3617     bool draw_image = false;
3618     bool supported_angle = false;
3619     int code = -1;
3620     opvp_result_t r = -1;
3621     int ecode = 0;
3622     int bits_per_pixel = 24;
3623     bool can_reverse = false;
3624     int p;
3625     float mag[2] = {1, 1};
3626     const gs_color_space *pcs = pim->ColorSpace;
3627 
3628     /* check if paths are too complex */
3629     if (!checkCPath(pcpath)) {
3630         return gx_default_begin_image(
3631                     dev, pis, pim, format,
3632                     prect, pdcolor, pcpath,
3633                     mem, pinfo);
3634     }
3635 
3636     color_index = 0;
3637 
3638     vinfo = gs_alloc_struct(mem, gdev_vector_image_enum_t,
3639                             &st_vector_image_enum,
3640                             "opvp_begin_image");
3641 
3642     if (vinfo) {
3643         memcpy(imageDecode,pim->Decode,sizeof(pim->Decode));
3644         vinfo->memory =mem;
3645         code = gdev_vector_begin_image(vdev, pis, pim, format, prect,
3646                                        pdcolor, pcpath, mem,
3647                                        &opvp_image_enum_procs,
3648                                        vinfo);
3649         if (code) ecode = code;
3650 
3651         if (!ecode) {
3652             /* bits per pixel */
3653             for (bits_per_pixel=0, p=0; p < vinfo->num_planes; p++) {
3654                 bits_per_pixel += vinfo->plane_depths[p];
3655             }
3656 
3657             /* for indexed color */
3658             if (!(pim->ImageMask)) {
3659                 color_index = gs_color_space_get_index(pcs);
3660                 if (color_index == gs_color_space_index_Indexed) {
3661                     base_color_index
3662                       = gs_color_space_indexed_base_space(pcs)->type->index;
3663                     if (((pcs->params.indexed.hival + 1) > 256)
3664                         || (bits_per_pixel != 8 && bits_per_pixel != 1)) {
3665                         return gx_default_begin_image(
3666                                 dev, pis, pim, format,
3667                                 prect, pdcolor, pcpath,
3668                                 mem, pinfo);
3669                     } else if (base_color_index
3670                          == gs_color_space_index_DeviceCMYK) {
3671                         /* for CMYK indexed color */
3672                         int count;
3673                         const unsigned char *p
3674                              = pcs->params.indexed.lookup.table.data;
3675                         frac rgb[3];
3676 
3677                         for(count = 0;count <
3678                              (pcs->params.indexed.hival + 1); count++) {
3679                             memset(rgb, 0, sizeof(rgb));
3680                             color_cmyk_to_rgb(
3681                                byte2frac((*(p + 0 + (count * 4)))),
3682                                byte2frac((*(p + 1 + (count * 4)))),
3683                                byte2frac((*(p + 2 + (count * 4)))),
3684                                byte2frac((*(p + 3 + (count * 4)))),
3685 #if GS_VERSION_MAJOR >= 9
3686                                pis, rgb, mem);
3687 #else
3688                                pis, rgb);
3689 #endif
3690                             *(palette + 0 + (count * 3)) = frac2byte(rgb[0]);
3691                             *(palette + 1 + (count * 3)) = frac2byte(rgb[1]);
3692                             *(palette + 2 + (count * 3)) = frac2byte(rgb[2]);
3693                         }
3694 
3695                         bits_per_pixel = 24;
3696                     } else if (base_color_index
3697                         == gs_color_space_index_DeviceRGB ||
3698                         base_color_index == gs_color_space_index_CIEABC) {
3699                         /* for RGB or CalRGB indexed color */
3700                         memcpy(palette, pcs->params.indexed.lookup.table.data,\
3701                         pcs->params.indexed.lookup.table.size);
3702                         bits_per_pixel = 24;
3703                     } else if (base_color_index
3704                         == gs_color_space_index_DeviceGray ||
3705                         base_color_index == gs_color_space_index_CIEA) {
3706                         /* for Gray or CalGray indexed color */
3707                         memcpy(palette, pcs->params.indexed.lookup.table.data,\
3708                         pcs->params.indexed.lookup.table.size);
3709                         bits_per_pixel = 8;
3710                     } else {
3711                         /* except CMYK and RGB */
3712                         return gx_default_begin_image(
3713                                     dev, pis, pim, format,
3714                                     prect, pdcolor, pcpath,
3715                                     mem, pinfo);
3716                     }
3717                 }
3718             }
3719 
3720 #if ENABLE_AUTO_REVERSE
3721             if (bits_per_pixel % 8 == 0) {
3722                 can_reverse = true;
3723             }
3724 #endif
3725             /* adjust matrix */
3726             reverse_image = false;
3727             gs_matrix_invert(&pim->ImageMatrix, &mtx);
3728             gs_matrix_multiply(&mtx, &ctm_only(pis), &mtx);
3729             switch (FastImageMode) {
3730             case FastImageNoCTM:
3731                 if ((mtx.xy==0)&&(mtx.yx==0)&& (mtx.yy>=0)) {
3732                     if (mtx.xx>=0) {
3733                         mag[0] = mtx.xx;
3734                         mag[1] = mtx.yy;
3735                         mtx.xx = 1;
3736                         mtx.yy = 1;
3737                         supported_angle = true;
3738                     } else if (can_reverse) {
3739                         mtx.xx *= -1;
3740                         mag[0] = mtx.xx;
3741                         mag[1] = mtx.yy;
3742                         mtx.xx = 1;
3743                         mtx.yy = 1;
3744                         mtx.tx -= vinfo->width
3745                                 * mag[0];
3746                         supported_angle = true;
3747                         reverse_image = true;
3748                     }
3749                 }
3750                 break;
3751             case FastImageNoRotate:
3752                 if ((mtx.xy==0)&&(mtx.yx==0)&& (mtx.yy>=0)) {
3753                     if (mtx.xx>=0) {
3754                         supported_angle = true;
3755                     } else if (can_reverse) {
3756                         mtx.xx *= -1;
3757                         mtx.tx -= vinfo->width
3758                                 * mtx.xx;
3759                         supported_angle = true;
3760                         reverse_image = true;
3761                     }
3762                 }
3763                 break;
3764             case FastImageRightAngle:
3765                 if ((mtx.xy==0)&&(mtx.yx==0)) {
3766                     if (((mtx.xx>=0)&&(mtx.yy>=0))||
3767                         ((mtx.xx<=0)&&(mtx.yy<=0))){
3768                         supported_angle = true;
3769                     } else if (can_reverse) {
3770                         mtx.xx *= -1;
3771                         mtx.tx -= vinfo->width
3772                                 * mtx.xx;
3773                         supported_angle = true;
3774                         reverse_image = true;
3775                     }
3776                 } else if ((mtx.xx==0)&&(mtx.yy==0)) {
3777                     if (((mtx.xy>=0)&&(mtx.yx<=0))||
3778                         ((mtx.xy<=0)&&(mtx.yx>=0))){
3779                         supported_angle = true;
3780                     } else if (can_reverse) {
3781                         mtx.xy *= -1;
3782                         mtx.ty -= vinfo->height
3783                                 * mtx.xy;
3784                         supported_angle = true;
3785                         reverse_image = true;
3786                     }
3787                 }
3788                 break;
3789             case FastImageReverseAngle:
3790                 if (((mtx.xy==0)&&(mtx.yx==0))||
3791                     ((mtx.xx==0)&&(mtx.yy==0))) {
3792                     supported_angle = true;
3793                 }
3794                 break;
3795             case FastImageAll:
3796                 supported_angle = true;
3797                 break;
3798             case FastImageDisable:
3799             default:
3800                 break;
3801             }
3802         }
3803 
3804         if ((!ecode) && supported_angle) {
3805             if ((!prect) &&
3806                 ((vinfo->num_planes == 1) ||
3807                  ((vinfo->num_planes == 3) &&
3808                   (vinfo->plane_depths[0] == 8) &&
3809                   (vinfo->plane_depths[1] == 8) &&
3810                   (vinfo->plane_depths[2] == 8))
3811                 )
3812                ) {
3813                 /*
3814                  * avail only
3815                  * 1 plane image
3816                  * or
3817                  * 3 planes 24 bits color image
3818                  * (8 bits per plane)
3819                  */
3820                 if (apiEntry->opvpStartDrawImage) {
3821                     draw_image = true;
3822                 }
3823             }
3824         }
3825     }
3826 
3827     if (draw_image) {
3828         *pinfo = (gx_image_enum_common_t *)vinfo;
3829 
3830         if (!ecode) {
3831             if (!pim->ImageMask) {
3832                 /* call SetPaintMode */
3833                 if (apiEntry->opvpSetPaintMode) {
3834                     apiEntry->opvpSetPaintMode(printerContext,
3835                        OPVP_PAINTMODE_OPAQUE);
3836                     change_paint_mode = true;
3837                 }
3838                 /* set color space */
3839                 if (apiEntry->opvpSetColorSpace != NULL) {
3840                     opvp_cspace_t ncspace;
3841 
3842                     savedColorSpace = colorSpace;
3843                     switch (bits_per_pixel) {
3844                     case 1:
3845                         ncspace = OPVP_CSPACE_DEVICEGRAY;
3846                         bits_per_pixel = 8;
3847                         if (!cspace_available[ncspace]) {
3848                             ncspace = OPVP_CSPACE_STANDARDRGB;
3849                             bits_per_pixel = 24;
3850                         }
3851                         break;
3852                     case 8:
3853                         ncspace = OPVP_CSPACE_DEVICEGRAY;
3854                         if (!cspace_available[ncspace]) {
3855                             ncspace = OPVP_CSPACE_STANDARDRGB;
3856                             bits_per_pixel = 24;
3857                         }
3858                         break;
3859                     case 24:
3860                         ncspace = OPVP_CSPACE_DEVICERGB;
3861                         if (!cspace_available[ncspace]) {
3862                             ncspace = OPVP_CSPACE_STANDARDRGB;
3863                         }
3864                         break;
3865                     default:
3866                         r = -1;
3867                         goto fallthrough;
3868                         break;
3869                     }
3870                     if (ncspace != colorSpace) {
3871                         if (apiEntry->opvpSetColorSpace(printerContext,ncspace)
3872                              != OPVP_OK) {
3873                             r = -1;
3874                             goto fallthrough;
3875                         }
3876                         colorSpace = ncspace;
3877                         change_cspace = true;
3878                     }
3879                 }
3880             }
3881         }
3882         if (!ecode) {
3883             if (supported_angle) {
3884                 /* moveto */
3885                 opvp_moveto(vdev, 0, 0, mtx.tx, mtx.ty, 0);
3886             }
3887             if ((supported_angle) && (FastImageMode != FastImageNoCTM)) {
3888                 /* call SetCTM */
3889                 ctm.a = mtx.xx;
3890                 ctm.b = mtx.xy;
3891                 ctm.c = mtx.yx;
3892                 ctm.d = mtx.yy;
3893                 ctm.e = mtx.tx;
3894                 ctm.f = mtx.ty;
3895                 if (apiEntry->opvpSetCTM) {
3896                     r = apiEntry->opvpSetCTM(printerContext, &ctm);
3897                 }
3898                 else r = -1;
3899                 if (r != OPVP_OK) ecode = r;
3900             }
3901         }
3902         if (!ecode) {
3903             int dw,dh;
3904 
3905             /* image size */
3906             if (mag[0] != 1) {
3907                 dw = floor(vinfo->width * mag[0]+0.5);
3908             } else {
3909                 dw = vinfo->width;
3910             }
3911             if (mag[1] != 1) {
3912                 dh = floor(vinfo->height * mag[1]+0.5);
3913             } else {
3914                 dh = vinfo->height;
3915             }
3916             /* call StartDrawImage */
3917             if (apiEntry->opvpStartDrawImage) {
3918                 opvp_int_t adj_raster;
3919 
3920                 adj_raster = bits_per_pixel*vinfo->width;
3921                 adj_raster = ((adj_raster+31) >> 5) << 2;
3922                 r = apiEntry->opvpStartDrawImage(
3923                                         printerContext,
3924                                         vinfo->width,
3925                                         vinfo->height,
3926                                         adj_raster,
3927                                         pim->ImageMask ?
3928                                           OPVP_IFORMAT_MASK:
3929                                           OPVP_IFORMAT_RAW,
3930                                         dw,dh);
3931                 if(r != OPVP_OK) {
3932                     if (apiEntry->opvpEndDrawImage) {
3933                         apiEntry->opvpEndDrawImage(printerContext);
3934                     }
3935                 }
3936             }
3937 
3938             /* bugfix for 32bit CMYK image print error */
3939 fallthrough:
3940             if(r != OPVP_OK) {
3941                 if (change_paint_mode) {
3942                     /* restore paint mode */
3943                     if (apiEntry->opvpSetPaintMode) {
3944                         apiEntry->opvpSetPaintMode(printerContext,
3945                            OPVP_PAINTMODE_TRANSPARENT);
3946                     }
3947                     change_paint_mode = false;
3948                 }
3949                 if (change_cspace) {
3950                     /* restore color space */
3951                     colorSpace = savedColorSpace;
3952                     if (apiEntry->opvpSetColorSpace) {
3953                         apiEntry->opvpSetColorSpace(printerContext,
3954                            colorSpace);
3955                     }
3956                     change_cspace = false;
3957                 }
3958                 if(apiEntry->opvpResetCTM) {
3959                     apiEntry->opvpResetCTM(printerContext); /* reset CTM */
3960                 }
3961                 return gx_default_begin_image(dev, pis, pim, format,
3962                                     prect, pdcolor, pcpath, mem, pinfo);
3963             }
3964         }
3965 
3966         if (!ecode) {
3967             begin_image = true;
3968         }
3969 
3970         return ecode;
3971     }
3972 
3973     return gx_default_begin_image(dev, pis, pim, format, prect,
3974                                   pdcolor, pcpath, mem, pinfo);
3975 }
3976 
3977 /*
3978  * plane data
3979  */
3980 static  int
opvp_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)3981 opvp_image_plane_data(
3982     gx_image_enum_common_t *info,
3983     const gx_image_plane_t *planes,
3984     int height,
3985     int *rows_used)
3986 {
3987     gdev_vector_image_enum_t *vinfo;
3988     byte *tmp_buf = NULL;
3989     byte *buf = NULL;
3990     int bits_per_pixel;
3991     int data_bytes, dst_bytes;
3992     int raster_length, dst_length;
3993     int p;
3994     int x;
3995     int d;
3996     int h;
3997     int ecode = 0;
3998     int i, j;
3999     byte *src_ptr, *dst_ptr, *ppalette;
4000     byte *ptr;
4001     bbox_image_enum *pbe;
4002     gx_image_enum *tinfo;
4003     const gs_imager_state *pis;
4004 
4005     vinfo = (gdev_vector_image_enum_t *)info;
4006 
4007     if (!begin_image) return 0;
4008 
4009     for (bits_per_pixel=0, p=0; p < vinfo->num_planes; p++) {
4010         bits_per_pixel += vinfo->plane_depths[p];
4011     }
4012 
4013     data_bytes = (bits_per_pixel * vinfo->width + 7) >> 3;
4014     raster_length = ((data_bytes + 3) >> 2) << 2;
4015     buf = calloc(raster_length, height);
4016 
4017     if (vinfo->default_info) {
4018         gx_image_plane_data(vinfo->default_info, planes, height);
4019     }
4020     if (vinfo->bbox_info) {
4021         gx_image_plane_data(vinfo->bbox_info, planes, height);
4022     }
4023 
4024     if (buf) {
4025         /* Adjust image data gamma */
4026         pbe = (bbox_image_enum *)vinfo->bbox_info;
4027         tinfo = (gx_image_enum *)pbe->target_info;
4028         pis = tinfo->pis;
4029 
4030         if (vinfo->num_planes == 1) {
4031             for (h = 0; h < height; h++) {
4032                 d = raster_length * h;
4033                 if (reverse_image) {
4034                     int bytes_per_pixel = bits_per_pixel / 8;
4035                     for (x = data_bytes * (h + 1) - bytes_per_pixel;
4036                           x >= data_bytes * h;
4037                           x-=bytes_per_pixel,
4038                           d+=bytes_per_pixel) {
4039                         memcpy(buf+d, planes[0].data+x, bytes_per_pixel);
4040                     }
4041                 } else {
4042                     memcpy(buf + d,
4043                            planes[0].data
4044                            + (data_bytes * h),
4045                            data_bytes);
4046                 }
4047             }
4048         } else {
4049             for (h = 0; h < height; h++) {
4050                 d = raster_length * h;
4051                 if (reverse_image) {
4052                     for (x = vinfo->width * (h + 1) - 1;
4053                          x >= vinfo->width * h;
4054                          x--) {
4055                         for (p = 0;
4056                              p < vinfo->num_planes;
4057                              p++, d++) {
4058                             buf[d] = (byte)(planes[p].data[x]);
4059                         }
4060                     }
4061                 } else {
4062                     for (x = vinfo->width * h;
4063                          x < vinfo->width * (h + 1);
4064                          x++) {
4065                         for (p = 0;
4066                              p < vinfo->num_planes;
4067                              p++, d++) {
4068                             buf[d] = (byte)
4069                                (planes[p].data[x]);
4070                         }
4071                     }
4072                 }
4073             }
4074         }
4075 
4076         if (tinfo->masked) {
4077             bool reverse = false;
4078 
4079             /* image mask */
4080             if (imageDecode[0] == 0) {
4081                 reverse = true;
4082             }
4083             if (reverse) {
4084                 for (i = 0; i < height; i++) {
4085                     src_ptr = buf + raster_length * i;
4086                     for (j = 0; j < data_bytes; j++) {
4087                         src_ptr[j] ^= 0xff;
4088                     }
4089                 }
4090             }
4091         } else {
4092             if(color_index == gs_color_space_index_Indexed) {
4093                 if (base_color_index == gs_color_space_index_DeviceGray ||
4094                    base_color_index == gs_color_space_index_CIEA) {
4095                     if (colorSpace == OPVP_CSPACE_DEVICEGRAY) {
4096                         /* Convert indexed gray color -> Gray */
4097                         if (bits_per_pixel == 8) { /* 8bit image */
4098                             dst_bytes = data_bytes;
4099                             dst_length = ((dst_bytes + 3) >> 2) << 2;
4100 
4101                             tmp_buf = calloc(dst_length, height);
4102                             if (tmp_buf) {
4103                                 for (i = 0; i < height; i++) {
4104                                     src_ptr = buf + raster_length * i;
4105                                     dst_ptr = tmp_buf + dst_length * i;
4106                                     for (j = 0; j < data_bytes; j++) {
4107                                         ppalette = palette + src_ptr[j] ;
4108                                         dst_ptr[j] = ppalette[0];
4109                                     }
4110                                 }
4111 
4112                                 free (buf);
4113                                 buf = tmp_buf;
4114                                 data_bytes = dst_bytes;
4115                                 raster_length = dst_length;
4116                                 vinfo->bits_per_pixel = 8;
4117                             }
4118                         } else { /* 1bit image */
4119                             dst_bytes = vinfo->width;
4120                             dst_length = ((dst_bytes + 3) >> 2) << 2;
4121 
4122                             tmp_buf = calloc(dst_length, height);
4123                             if (tmp_buf) {
4124                                 for (i = 0; i < height; i++) {
4125                                     src_ptr = buf + raster_length * i;
4126                                     dst_ptr = tmp_buf + dst_length * i;
4127                                     for (j = 0; j < vinfo->width; j++) {
4128                                         int o = ((src_ptr[j/8] & (1 << (7 - (j & 7))))
4129                                                    != 0);
4130                                         ppalette = palette + o;
4131                                         dst_ptr[j] = ppalette[0];
4132                                     }
4133                                 }
4134 
4135                                 free (buf);
4136                                 buf = tmp_buf;
4137                                 data_bytes = dst_bytes;
4138                                 raster_length = dst_length;
4139                                 vinfo->bits_per_pixel = 8;
4140                             }
4141                         }
4142                     } else {
4143                         /* Convert indexed Gray color -> RGB */
4144                         if (bits_per_pixel == 8) { /* 8bit image */
4145                             dst_bytes = data_bytes * 3;
4146                             dst_length = ((dst_bytes + 3) >> 2) << 2;
4147 
4148                             tmp_buf = calloc(dst_length, height);
4149                             if (tmp_buf) {
4150                                 for (i = 0; i < height; i++) {
4151                                     src_ptr = buf + raster_length * i;
4152                                     dst_ptr = tmp_buf + dst_length * i;
4153                                     for (j = 0; j < data_bytes; j++) {
4154                                         ppalette = palette + src_ptr[j] * 3;
4155                                         dst_ptr[j*3] = ppalette[0]; /* R */
4156                                         dst_ptr[j*3 + 1] = ppalette[0]; /* G */
4157                                         dst_ptr[j*3 + 2] = ppalette[0]; /* B */
4158                                     }
4159                                 }
4160 
4161                                 free (buf);
4162                                 buf = tmp_buf;
4163                                 data_bytes = dst_bytes;
4164                                 raster_length = dst_length;
4165                                 vinfo->bits_per_pixel = 24;
4166                             }
4167                         } else { /* 1bit image */
4168                             dst_bytes = vinfo->width * 3;
4169                             dst_length = ((dst_bytes + 3) >> 2) << 2;
4170 
4171                             tmp_buf = calloc(dst_length, height);
4172                             if (tmp_buf) {
4173                                 for (i = 0; i < height; i++) {
4174                                     src_ptr = buf + raster_length * i;
4175                                     dst_ptr = tmp_buf + dst_length * i;
4176                                     for (j = 0; j < vinfo->width; j++) {
4177                                         int o = ((src_ptr[j/8] & (1 << (7 - (j & 7))))
4178                                                    != 0);
4179                                         ppalette = palette + o * 3;
4180                                         dst_ptr[j*3] = ppalette[0]; /* R */
4181                                         dst_ptr[j*3 + 1] = ppalette[0]; /* G */
4182                                         dst_ptr[j*3 + 2] = ppalette[0]; /* B */
4183                                     }
4184                                 }
4185 
4186                                 free (buf);
4187                                 buf = tmp_buf;
4188                                 data_bytes = dst_bytes;
4189                                 raster_length = dst_length;
4190                                 vinfo->bits_per_pixel = 24;
4191                             }
4192                         }
4193                     }
4194                 } else {
4195                     /* Convert indexed color -> RGB */
4196                     if (bits_per_pixel == 8) { /* 8bit image */
4197                         dst_bytes = data_bytes * 3;
4198                         dst_length = ((dst_bytes + 3) >> 2) << 2;
4199 
4200                         tmp_buf = calloc(dst_length, height);
4201                         if (tmp_buf) {
4202                             for (i = 0; i < height; i++) {
4203                                 src_ptr = buf + raster_length * i;
4204                                 dst_ptr = tmp_buf + dst_length * i;
4205                                 for (j = 0; j < data_bytes; j++) {
4206                                     ppalette = palette + src_ptr[j] * 3;
4207                                     dst_ptr[j*3] = ppalette[0]; /* R */
4208                                     dst_ptr[j*3 + 1] = ppalette[1]; /* G */
4209                                     dst_ptr[j*3 + 2] = ppalette[2]; /* B */
4210                                 }
4211                             }
4212 
4213                             free (buf);
4214                             buf = tmp_buf;
4215                             data_bytes = dst_bytes;
4216                             raster_length = dst_length;
4217                             vinfo->bits_per_pixel = 24;
4218                         }
4219                     } else { /* 1bit image */
4220                         dst_bytes = vinfo->width * 3;
4221                         dst_length = ((dst_bytes + 3) >> 2) << 2;
4222 
4223                         tmp_buf = calloc(dst_length, height);
4224                         if (tmp_buf) {
4225                             for (i = 0; i < height; i++) {
4226                                 src_ptr = buf + raster_length * i;
4227                                 dst_ptr = tmp_buf + dst_length * i;
4228                                 for (j = 0; j < vinfo->width; j++) {
4229                                     int o = ((src_ptr[j/8] & (1 << (7 - (j & 7))))
4230                                                != 0);
4231                                     ppalette = palette + o * 3;
4232                                     dst_ptr[j*3] = ppalette[0]; /* R */
4233                                     dst_ptr[j*3 + 1] = ppalette[1]; /* G */
4234                                     dst_ptr[j*3 + 2] = ppalette[2]; /* B */
4235                                 }
4236                             }
4237 
4238                             free (buf);
4239                             buf = tmp_buf;
4240                             data_bytes = dst_bytes;
4241                             raster_length = dst_length;
4242                             vinfo->bits_per_pixel = 24;
4243                         }
4244                     }
4245                 }
4246             }
4247 
4248             /* Convert Gray */
4249             if(color_index == gs_color_space_index_DeviceGray ||
4250                color_index == gs_color_space_index_CIEA) {
4251                 if (colorSpace == OPVP_CSPACE_STANDARDRGB
4252                   || colorSpace == OPVP_CSPACE_DEVICERGB) {
4253                     /* convert to RGB */
4254                     if (bits_per_pixel == 8) { /* 8bit image */
4255                         dst_bytes = data_bytes * 3;
4256                         dst_length = ((dst_bytes + 3) >> 2) << 2;
4257 
4258                         tmp_buf = calloc(dst_length, height);
4259                         if (tmp_buf) {
4260                             for (i = 0; i < height; i++) {
4261                                 src_ptr = buf + raster_length * i;
4262                                 dst_ptr = tmp_buf + dst_length * i;
4263                                 for (j = 0; j < data_bytes; j++) {
4264                                     unsigned char d = floor(
4265                                       imageDecode[0]*255 + src_ptr[j]*
4266                                       (imageDecode[1]-imageDecode[0])+0.5);
4267 
4268                                     dst_ptr[j*3] = d; /* R */
4269                                     dst_ptr[j*3 + 1] = d; /* G */
4270                                     dst_ptr[j*3 + 2] = d; /* B */
4271                                 }
4272                             }
4273 
4274                             free (buf);
4275                             buf = tmp_buf;
4276                             data_bytes = dst_bytes;
4277                             raster_length = dst_length;
4278                             vinfo->bits_per_pixel = 24;
4279                         }
4280                     } else { /* 1bit image */
4281                         dst_bytes = vinfo->width * 3;
4282                         dst_length = ((dst_bytes + 3) >> 2) << 2;
4283 
4284                         tmp_buf = calloc(dst_length, height);
4285                         if (tmp_buf) {
4286                             for (i = 0; i < height; i++) {
4287                                 src_ptr = buf + raster_length * i;
4288                                 dst_ptr = tmp_buf + dst_length * i;
4289                                 for (j = 0; j < vinfo->width; j++) {
4290                                     int o = ((src_ptr[j/8] & (1 << (7 - (j & 7))))
4291                                               != 0);
4292                                     unsigned char d = floor(
4293                                       imageDecode[0]*255 + o*
4294                                       (imageDecode[1]-imageDecode[0])*255+0.5);
4295                                     dst_ptr[j*3] = d; /* R */
4296                                     dst_ptr[j*3 + 1] = d; /* G */
4297                                     dst_ptr[j*3 + 2] =d; /* B */
4298                                 }
4299                             }
4300 
4301                             free (buf);
4302                             buf = tmp_buf;
4303                             data_bytes = dst_bytes;
4304                             raster_length = dst_length;
4305                             vinfo->bits_per_pixel = 24;
4306                         }
4307                     }
4308                 } else if (colorSpace == OPVP_CSPACE_DEVICEGRAY) {
4309                     if (bits_per_pixel == 1) { /* 1bit image */
4310                         dst_bytes = vinfo->width;
4311                         dst_length = ((dst_bytes + 3) >> 2) << 2;
4312 
4313                         tmp_buf = calloc(dst_length, height);
4314                         if (tmp_buf) {
4315                             for (i = 0; i < height; i++) {
4316                                 src_ptr = buf + raster_length * i;
4317                                 dst_ptr = tmp_buf + dst_length * i;
4318                                 for (j = 0; j < vinfo->width; j++) {
4319                                     int o = ((src_ptr[j/8] & (1 << (7 - (j & 7))))
4320                                               != 0);
4321                                     unsigned char d = floor(
4322                                       imageDecode[0]*255 + o*
4323                                       (imageDecode[1]-imageDecode[0])*255+0.5);
4324                                     dst_ptr[j] = d; /* R */
4325                                 }
4326                             }
4327 
4328                             free (buf);
4329                             buf = tmp_buf;
4330                             data_bytes = dst_bytes;
4331                             raster_length = dst_length;
4332                             vinfo->bits_per_pixel = 8;
4333                         }
4334                     }
4335                 }
4336             }
4337         }
4338 #if GS_VERSION_MAJOR >= 8
4339         if (vinfo->bits_per_pixel == 24) { /* 24bit RGB color */
4340             for (i = 0; i < height; i++) {
4341                 ptr = buf + raster_length * i;
4342                 for (j = 0; j < vinfo->width; j++) {
4343                     ptr[j*3] = min(255, frac2cv(gx_map_color_frac(pis,
4344                       cv2frac(ptr[j*3]), effective_transfer[0])));
4345                     ptr[j*3+1] = min(255, frac2cv(gx_map_color_frac(pis,
4346                       cv2frac(ptr[j*3+1]), effective_transfer[1])));
4347                     ptr[j*3+2] = min(255, frac2cv(gx_map_color_frac(pis,
4348                       cv2frac(ptr[j*3+2]), effective_transfer[2])));
4349                 }
4350             }
4351         } else if (vinfo->bits_per_pixel == 8) { /* 8bit Gray image */
4352             for (i = 0; i < height; i++) {
4353                 ptr = buf + raster_length * i;
4354                 for (j=0; j < vinfo->width; j++) {
4355                     ptr[j] = min(255, frac2cv(gx_map_color_frac(pis,
4356                       cv2frac(ptr[j]), effective_transfer[3])));
4357                 }
4358             }
4359         }
4360 #else
4361         if (vinfo->bits_per_pixel == 24) { /* 24bit RGB color */
4362             for (i = 0; i < height; i++) {
4363                 ptr = buf + raster_length * i;
4364                 for (j = 0; j < vinfo->width; j++) {
4365                     ptr[j*3] = min(255, frac2cv(gx_map_color_frac(pis,
4366                       cv2frac(ptr[j*3]), effective_transfer.colored.red)));
4367                     ptr[j*3+1] = min(255, frac2cv(gx_map_color_frac(pis,
4368                       cv2frac(ptr[j*3+1]), effective_transfer.colored.green)));
4369                     ptr[j*3+2] = min(255, frac2cv(gx_map_color_frac(pis,
4370                       cv2frac(ptr[j*3+2]), effective_transfer.colored.blue)));
4371                 }
4372             }
4373         } else if (vinfo->bits_per_pixel == 8) { /* 8bit Gray image */
4374             for (i = 0; i < height; i++) {
4375                 ptr = buf + raster_length * i;
4376                 for (j = 0; j < vinfo->width; j++) {
4377                     ptr[j] = min(255, frac2cv(gx_map_color_frac(pis,
4378                       cv2frac(ptr[j]), effective_transfer.colored.gray)));
4379                 }
4380             }
4381         }
4382 #endif
4383 
4384         /* call TansferDrawImage */
4385         if (apiEntry->opvpTransferDrawImage) {
4386             apiEntry->opvpTransferDrawImage(printerContext,
4387                         raster_length * height, (void *)buf);
4388         }
4389         if (buf) {
4390             free(buf); /* free buffer */
4391         }
4392     }
4393 
4394     vinfo->y += height;
4395     ecode = (vinfo->y >= vinfo->height);
4396 
4397     return ecode;
4398 }
4399 
4400 /*
4401  * end image
4402  */
4403 static  int
opvp_image_end_image(gx_image_enum_common_t * info,bool draw_last)4404 opvp_image_end_image(gx_image_enum_common_t *info, bool draw_last)
4405 {
4406     gx_device *dev = info->dev;
4407     gx_device_vector *vdev = (gx_device_vector *)dev;
4408     gdev_vector_image_enum_t *vinfo;
4409     opvp_ctm_t ctm;
4410 
4411     vinfo = (gdev_vector_image_enum_t *)info;
4412 
4413     if (begin_image) {
4414         /* call EndDrawImage */
4415         if (apiEntry->opvpEndDrawImage) {
4416             apiEntry->opvpEndDrawImage(printerContext);
4417         }
4418 
4419         begin_image = false;
4420 
4421         if (FastImageMode != FastImageNoCTM) {
4422             /* call ResetCTM */
4423             if (apiEntry->opvpResetCTM) {
4424                 apiEntry->opvpResetCTM(printerContext);
4425             } else {
4426                 /* call SetCTM */
4427                 ctm.a = 1;
4428                 ctm.b = 0;
4429                 ctm.c = 0;
4430                 ctm.d = 1;
4431                 ctm.e = 0;
4432                 ctm.f = 0;
4433                 if (apiEntry->opvpSetCTM) {
4434                     apiEntry->opvpSetCTM(printerContext, &ctm);
4435                 }
4436             }
4437         }
4438         if (change_paint_mode) {
4439             /* restore paint mode */
4440             if (apiEntry->opvpSetPaintMode) {
4441                 apiEntry->opvpSetPaintMode(printerContext,
4442                    OPVP_PAINTMODE_TRANSPARENT);
4443             }
4444             change_paint_mode = false;
4445         }
4446         if (change_cspace) {
4447             /* restore color space */
4448             colorSpace = savedColorSpace;
4449             if (apiEntry->opvpSetColorSpace) {
4450                 apiEntry->opvpSetColorSpace(printerContext,
4451                    colorSpace);
4452             }
4453             change_cspace = false;
4454         }
4455     }
4456 
4457     return gdev_vector_end_image(vdev, vinfo, draw_last, vdev->white);
4458 }
4459 
4460 /* ----- vector driver procs ----- */
4461 /*
4462  * begin page
4463  */
4464 static  int
opvp_beginpage(gx_device_vector * vdev)4465 opvp_beginpage(gx_device_vector *vdev)
4466 {
4467     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4468     int code = -1;
4469     int ecode = 0;
4470 
4471 #ifdef OPVP_IGNORE_BLANK_PAGE
4472     if (pdev->in_page) return 0;
4473 #endif
4474     /* start page */
4475     code = opvp_startpage((gx_device *)pdev);
4476     if (code) {
4477         ecode = code;
4478     } else {
4479         pdev->in_page = true;   /* added '05.12.07 */
4480         beginPage = true;
4481     }
4482 
4483     return ecode;
4484 }
4485 
4486 /*
4487  * set line width
4488  */
4489 static  int
opvp_setlinewidth(gx_device_vector * vdev,floatp width)4490 opvp_setlinewidth(gx_device_vector *vdev, floatp width)
4491 {
4492     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4493     opvp_result_t r = -1;
4494     int ecode = 0;
4495     opvp_fix_t w;
4496 
4497     /* check page-in */
4498     if (opvp_check_in_page(pdev)) return -1;
4499 
4500     /* call SetLineWidth */
4501     OPVP_F2FIX(width, w);
4502     if (apiEntry->opvpSetLineWidth) {
4503         r = apiEntry->opvpSetLineWidth(printerContext, w);
4504     }
4505     if (r != OPVP_OK) {
4506         ecode = -1;
4507     }
4508 
4509     return ecode;
4510 }
4511 
4512 /*
4513  * set line cap
4514  */
4515 static  int
opvp_setlinecap(gx_device_vector * vdev,gs_line_cap cap)4516 opvp_setlinecap(gx_device_vector *vdev, gs_line_cap cap)
4517 {
4518     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4519     opvp_result_t r = -1;
4520     int ecode = 0;
4521     opvp_linecap_t linecap;
4522 
4523     /* check page-in */
4524     if (opvp_check_in_page(pdev)) return -1;
4525 
4526     switch (cap) {
4527     case gs_cap_butt:
4528         linecap = OPVP_LINECAP_BUTT;
4529         break;
4530     case gs_cap_round:
4531         linecap = OPVP_LINECAP_ROUND;
4532         break;
4533     case gs_cap_square:
4534         linecap = OPVP_LINECAP_SQUARE;
4535         break;
4536     case gs_cap_triangle:
4537     default:
4538         linecap = OPVP_LINECAP_BUTT;
4539         break;
4540     }
4541 
4542     /* call SetLineCap */
4543     if (apiEntry->opvpSetLineCap) {
4544         r = apiEntry->opvpSetLineCap(printerContext, linecap);
4545     }
4546     if (r != OPVP_OK) {
4547         ecode = -1;
4548     }
4549 
4550     return ecode;
4551 }
4552 
4553 /*
4554  * set line join
4555  */
4556 static  int
opvp_setlinejoin(gx_device_vector * vdev,gs_line_join join)4557 opvp_setlinejoin(gx_device_vector *vdev, gs_line_join join)
4558 {
4559     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4560     opvp_result_t r = -1;
4561     int ecode = 0;
4562     opvp_linejoin_t linejoin;
4563 
4564     /* check page-in */
4565     if (opvp_check_in_page(pdev)) return -1;
4566 
4567     switch (join) {
4568     case gs_join_miter:
4569         linejoin = OPVP_LINEJOIN_MITER;
4570         break;
4571     case gs_join_round:
4572         linejoin = OPVP_LINEJOIN_ROUND;
4573         break;
4574     case gs_join_bevel:
4575         linejoin = OPVP_LINEJOIN_BEVEL;
4576         break;
4577     case gs_join_none:
4578     case gs_join_triangle:
4579     default:
4580         linejoin = OPVP_LINEJOIN_MITER;
4581         break;
4582     }
4583 
4584     /* call SetLineJoin */
4585     if (apiEntry->opvpSetLineJoin) {
4586         r = apiEntry->opvpSetLineJoin(printerContext, linejoin);
4587     }
4588     if (r != OPVP_OK) {
4589         ecode = -1;
4590     }
4591 
4592     return ecode;
4593 }
4594 
4595 /*
4596  * set miter limit
4597  */
4598 static  int
opvp_setmiterlimit(gx_device_vector * vdev,floatp limit)4599 opvp_setmiterlimit(gx_device_vector *vdev, floatp limit)
4600 {
4601     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4602     opvp_result_t r = -1;
4603     int ecode = 0;
4604     opvp_fix_t l;
4605 
4606     /* check page-in */
4607     if (opvp_check_in_page(pdev)) return -1;
4608 
4609     /* call SetMiterLimit */
4610     OPVP_F2FIX(limit, l);
4611     if (apiEntry->opvpSetMiterLimit) {
4612         r = apiEntry->opvpSetMiterLimit(printerContext, l);
4613     }
4614     if (r != OPVP_OK) {
4615         ecode = -1;
4616     }
4617 
4618     return ecode;
4619 }
4620 
4621 /*
4622  * set dash
4623  */
4624 static  int
opvp_setdash(gx_device_vector * vdev,const float * pattern,uint count,floatp offset)4625 opvp_setdash(
4626     gx_device_vector *vdev,
4627     const float *pattern,
4628     uint count,
4629     floatp offset)
4630 {
4631     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4632     opvp_result_t r = -1;
4633     int ecode = 0;
4634     opvp_fix_t *p = NULL;
4635     opvp_fix_t o;
4636     int i;
4637 
4638     /* check page-in */
4639     if (opvp_check_in_page(pdev)) return -1;
4640 
4641     /* pattern */
4642     if (count) {
4643         p = calloc(sizeof(opvp_fix_t), count);
4644         if (p) {
4645             for (i = 0; i < count; i++) {
4646                 OPVP_F2FIX(pattern[i], p[i]);
4647             }
4648         } else {
4649             ecode = -1;
4650         }
4651     }
4652 
4653     /* call SetLineDash */
4654     if (!ecode) {
4655         if (apiEntry->opvpSetLineDash) {
4656             r = apiEntry->opvpSetLineDash(printerContext, count,p);
4657         }
4658         if (r != OPVP_OK) {
4659             ecode = -1;
4660         }
4661     }
4662 
4663     /* call SetLineDashOffset */
4664     if (!ecode) {
4665         OPVP_F2FIX(offset, o);
4666         if (apiEntry->opvpSetLineDashOffset) {
4667             r = apiEntry->opvpSetLineDashOffset(printerContext, o);
4668         }
4669         if (r != OPVP_OK) {
4670             ecode = -1;
4671         }
4672     }
4673 
4674     /* call SetLineStyle */
4675     if (!ecode) {
4676         if (apiEntry->opvpSetLineStyle) {
4677             r = apiEntry->opvpSetLineStyle(printerContext,
4678                                   (count ?
4679                                    OPVP_LINESTYLE_DASH :
4680                                    OPVP_LINESTYLE_SOLID));
4681         }
4682         if (r != OPVP_OK) {
4683             ecode = -1;
4684         }
4685     }
4686 
4687     if (p) free(p);
4688 
4689     return ecode;
4690 }
4691 
4692 /*
4693  * set flat
4694  */
4695 static  int
opvp_setflat(gx_device_vector * vdev,floatp flatness)4696 opvp_setflat(gx_device_vector *vdev, floatp flatness)
4697 {
4698     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4699     int ecode = 0;
4700 
4701     /* check page-in */
4702     if (opvp_check_in_page(pdev)) return -1;
4703 
4704     /* what to do ? */
4705 
4706     return ecode;
4707 }
4708 
4709 /*
4710  * set logical operation
4711  */
4712 static  int
opvp_setlogop(gx_device_vector * vdev,gs_logical_operation_t lop,gs_logical_operation_t diff)4713 opvp_setlogop(
4714     gx_device_vector *vdev,
4715     gs_logical_operation_t lop,
4716     gs_logical_operation_t diff)
4717 {
4718     /* nothing done */
4719     return 0;
4720 }
4721 
4722 #if GS_VERSION_MAJOR >= 8
4723 /*--- added for Ghostscritp 8.15 ---*/
4724 static int
opvp_can_handle_hl_color(gx_device_vector * vdev,const gs_imager_state * pis1,const gx_drawing_color * pdc)4725 opvp_can_handle_hl_color(gx_device_vector * vdev,
4726               const gs_imager_state * pis1, const gx_drawing_color * pdc)
4727 {
4728     return false; /* High level color is not implemented yet. */
4729 }
4730 #endif
4731 
4732 /*
4733  * set fill color
4734  */
4735 #if GS_VERSION_MAJOR >= 8
4736 static  int
opvp_setfillcolor(gx_device_vector * vdev,const gs_imager_state * pis,const gx_drawing_color * pdc)4737 opvp_setfillcolor(
4738     gx_device_vector *vdev,
4739     const gs_imager_state *pis, /* added for gs 8.15 */
4740     const gx_drawing_color *pdc)
4741 #else
4742 static  int
4743 opvp_setfillcolor(gx_device_vector *vdev, const gx_drawing_color *pdc)
4744 #endif
4745 {
4746     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4747     opvp_result_t r = -1;
4748     int ecode = 0;
4749     gx_color_index color;
4750     static opvp_brush_t brush;
4751 
4752     /* check page-in */
4753     if (opvp_check_in_page(pdev)) return -1;
4754 
4755     if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck);
4756 
4757     /* color */
4758     if (!vectorFillColor) vectorFillColor = &brush;
4759     color = gx_dc_pure_color(pdc);
4760     opvp_set_brush_color(pdev, color, vectorFillColor);
4761 
4762     /* call SetFillColor */
4763     if (apiEntry->opvpSetFillColor) {
4764         r = apiEntry->opvpSetFillColor(printerContext, vectorFillColor);
4765     }
4766     if (r != OPVP_OK) {
4767         ecode = -1;
4768     }
4769 
4770     return ecode;
4771 }
4772 
4773 /*
4774  * set stroke color
4775  */
4776 #if GS_VERSION_MAJOR >= 8
4777 static  int
opvp_setstrokecolor(gx_device_vector * vdev,const gs_imager_state * pis,const gx_drawing_color * pdc)4778 opvp_setstrokecolor(
4779     gx_device_vector *vdev,
4780     const gs_imager_state *pis, /* added for gs 8.15 */
4781     const gx_drawing_color *pdc)
4782 #else
4783 static  int
4784 opvp_setstrokecolor(gx_device_vector *vdev, const gx_drawing_color *pdc)
4785 #endif
4786 {
4787     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4788     opvp_result_t r = -1;
4789     int ecode = 0;
4790     gx_color_index color;
4791     opvp_brush_t brush;
4792 
4793     /* check page-in */
4794     if (opvp_check_in_page(pdev)) return -1;
4795 
4796     if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck);
4797 
4798     /* color */
4799     color = gx_dc_pure_color(pdc);
4800     opvp_set_brush_color(pdev, color, &brush);
4801 
4802     /* call SetStrokeColor */
4803     if (apiEntry->opvpSetStrokeColor) {
4804         r = apiEntry->opvpSetStrokeColor(printerContext, &brush);
4805     }
4806     if (r != OPVP_OK) {
4807         ecode = -1;
4808     }
4809 
4810     return ecode;
4811 }
4812 
4813 #define OPVP_OPT_MULTI_PATH
4814 
4815 /*
4816  * vector do path
4817  */
4818 static  int
opvp_vector_dopath(gx_device_vector * vdev,const gx_path * ppath,gx_path_type_t type,const gs_matrix * pmat)4819 opvp_vector_dopath(
4820     gx_device_vector *vdev,
4821     const gx_path *ppath,
4822     gx_path_type_t type,
4823     const gs_matrix *pmat)
4824 {
4825     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
4826     opvp_result_t r = -1;
4827     int code = -1;
4828     int ecode = 0;
4829     gs_fixed_rect rect;
4830     gs_path_enum path;
4831     gs_point scale;
4832     int op;
4833 #ifdef  OPVP_OPT_MULTI_PATH
4834     int i;
4835     int pop = 0;
4836     int npoints = 0;
4837     int *cp_num = NULL;
4838     _fPoint *points = NULL;
4839     opvp_point_t *opvp_p = NULL;
4840     _fPoint current;
4841     _fPoint check_p;
4842 #else
4843     _fPoint points[4];
4844 #endif
4845     _fPoint start;
4846     fixed vs[6];
4847     bool begin = true;
4848 
4849     start.x = start.y = 0;
4850 #ifdef  OPVP_OPT_MULTI_PATH
4851     current.x = current.y = 0;
4852 #endif
4853     /* check page-in */
4854     if (opvp_check_in_page(pdev)) return -1;
4855 
4856     if (gx_path_is_rectangle(ppath, &rect))
4857     return (*vdev_proc(vdev, dorect))(vdev,
4858                                       rect.p.x, rect.p.y,
4859                                       rect.q.x, rect.q.y,
4860                                       type);
4861 
4862     /* begin path */
4863     code = (*vdev_proc(vdev, beginpath))(vdev, type);
4864     if (code) ecode = code;
4865     scale = vdev->scale;
4866     gx_path_enum_init(&path, ppath);
4867 
4868     while (!ecode) {
4869         op = gx_path_enum_next(&path, (gs_fixed_point *)vs);
4870         if (begin) {
4871             /* start point */
4872             start.x = fixed2float(vs[0]) / scale.x;
4873             start.y = fixed2float(vs[1]) / scale.y;
4874             begin = false;
4875 
4876 #ifdef  OPVP_OPT_MULTI_PATH
4877             npoints = 1;
4878             points = realloc(points, sizeof(_fPoint));
4879             current = start;
4880 #endif
4881 
4882             points[0] = start;
4883 
4884 #ifdef  OPVP_OPT_MULTI_PATH
4885         } else if (op != pop) {
4886             /* convert float to Fix */
4887             opvp_p = realloc(opvp_p, sizeof(opvp_point_t) * npoints);
4888             for (i = 0; i < npoints; i++) {
4889                 OPVP_F2FIX(points[i].x, opvp_p[i].x);
4890                 OPVP_F2FIX(points[i].y, opvp_p[i].y);
4891             }
4892 
4893             switch (pop) {
4894             case gs_pe_moveto:
4895                 /* call SetCurrentPoint */
4896                 if (apiEntry->opvpSetCurrentPoint) {
4897                     r = apiEntry->opvpSetCurrentPoint(
4898                        printerContext,
4899                        opvp_p[npoints-1].x,
4900                        opvp_p[npoints-1].y);
4901                 }
4902                 if (r != OPVP_OK) ecode = -1;
4903                 break;
4904             case gs_pe_lineto:
4905                 /* call LinePath */
4906                 if (apiEntry->opvpLinePath) {
4907                     r = apiEntry->opvpLinePath(
4908                        printerContext,
4909                        OPVP_PATHOPEN,
4910                        npoints - 1,
4911                        &(opvp_p[1]));
4912                 }
4913                 if (r != OPVP_OK) ecode = -1;
4914                 break;
4915             case gs_pe_curveto:
4916                 /* npoints */
4917                 if (!cp_num)
4918                 cp_num = calloc(sizeof(int), 2);
4919                 cp_num[0] = npoints;
4920                 cp_num[1] = 0;
4921 
4922                 /* call BezierPath */
4923                 if (apiEntry->opvpBezierPath) {
4924                     r = apiEntry->opvpBezierPath(
4925                        printerContext,
4926                        npoints - 1,
4927                        &(opvp_p[1])
4928                        );
4929                 }
4930                 if (r != OPVP_OK) ecode = -1;
4931                 break;
4932             case gs_pe_closepath:
4933                     /* close path */
4934                     break;
4935             default:
4936                 /* error */
4937                 return_error(gs_error_unknownerror);
4938                 break;
4939             }
4940 
4941             /* reset */
4942             npoints = 1;
4943             if (cp_num) free(cp_num), cp_num = NULL;
4944             points = realloc(points, sizeof(_fPoint));
4945             points[0] = current;
4946 #endif
4947         }
4948 
4949         if (!op) break; /* END */
4950 
4951         switch (op) {
4952         case gs_pe_moveto:
4953 #ifdef  OPVP_OPT_MULTI_PATH
4954             /* move to */
4955             i = npoints;
4956             npoints += 1;
4957             points = realloc(points, sizeof(_fPoint) * npoints);
4958             points[i].x = fixed2float(vs[0]) / scale.x;
4959             points[i].y = fixed2float(vs[1]) / scale.y;
4960             current = points[i];
4961             start = current;
4962 
4963 #else
4964 
4965             /* move to */
4966             points[1].x = fixed2float(vs[0]) / scale.x;
4967             points[1].y = fixed2float(vs[1]) / scale.y;
4968             code = (*vdev_proc(vdev, moveto))(vdev,
4969                                               points[0].x,
4970                                               points[0].y,
4971                                               points[1].x,
4972                                               points[1].y,
4973                                               type);
4974             if (code) ecode = code;
4975             points[0] = points[1];
4976             start = points[0];
4977 #endif
4978             break;
4979         case gs_pe_lineto:
4980 #ifdef  OPVP_OPT_MULTI_PATH
4981             /* line to */
4982             i = npoints;
4983             npoints += 1;
4984             points = realloc(points, sizeof(_fPoint) * npoints);
4985             points[i].x = fixed2float(vs[0]) / scale.x;
4986             points[i].y = fixed2float(vs[1]) / scale.y;
4987             current = points[i];
4988 #else
4989             /* line to */
4990             points[1].x = fixed2float(vs[0]) / scale.x;
4991             points[1].y = fixed2float(vs[1]) / scale.y;
4992             code = (*vdev_proc(vdev, lineto))(vdev,
4993                                               points[0].x,
4994                                               points[0].y,
4995                                               points[1].x,
4996                                               points[1].y,
4997                                               type);
4998             if (code) ecode = code;
4999             points[0] = points[1];
5000 #endif
5001             break;
5002         case gs_pe_curveto:
5003 #ifdef  OPVP_OPT_MULTI_PATH
5004             /* curve to */
5005             check_p.x = fixed2float(vs[0]) / scale.x;
5006             check_p.y = fixed2float(vs[1]) / scale.y;
5007 
5008             i = npoints;
5009             npoints += 3;
5010             points = realloc(points, sizeof(_fPoint) * npoints);
5011             points[i  ].x = fixed2float(vs[0]) / scale.x;
5012             points[i  ].y = fixed2float(vs[1]) / scale.y;
5013             points[i+1].x = fixed2float(vs[2]) / scale.x;
5014             points[i+1].y = fixed2float(vs[3]) / scale.y;
5015             points[i+2].x = fixed2float(vs[4]) / scale.x;
5016             points[i+2].y = fixed2float(vs[5]) / scale.y;
5017             current = points[i+2];
5018 #else
5019             /* curve to */
5020             points[1].x = fixed2float(vs[0]) / scale.x;
5021             points[1].y = fixed2float(vs[1]) / scale.y;
5022             points[2].x = fixed2float(vs[2]) / scale.x;
5023             points[2].y = fixed2float(vs[3]) / scale.y;
5024             points[3].x = fixed2float(vs[4]) / scale.x;
5025             points[3].y = fixed2float(vs[5]) / scale.y;
5026             code = (*vdev_proc(vdev, curveto))(vdev,
5027                                                points[0].x,
5028                                                points[0].y,
5029                                                points[1].x,
5030                                                points[1].y,
5031                                                points[2].x,
5032                                                points[2].y,
5033                                                points[3].x,
5034                                                points[3].y,
5035                                                type);
5036             if (code) ecode = code;
5037             points[0] = points[3];
5038 #endif
5039             break;
5040         case gs_pe_closepath:
5041             /* close path */
5042             code = (*vdev_proc(vdev, closepath))(
5043                        vdev,
5044                        points[0].x,
5045                        points[0].y,
5046                        start.x,
5047                        start.y,
5048                        type);
5049             if (code) ecode = code;
5050             points[0] = start;
5051 #ifdef  OPVP_OPT_MULTI_PATH
5052             current = start;
5053 #endif
5054             break;
5055         default:
5056             /* error */
5057             return_error(gs_error_unknownerror);
5058             break;
5059         }
5060 
5061 #ifdef  OPVP_OPT_MULTI_PATH
5062         pop = op;
5063 #endif
5064     }
5065 
5066     /* end path */
5067     code = (*vdev_proc(vdev, endpath))(vdev, type);
5068     if (code) ecode = code;
5069 
5070 #ifdef  OPVP_OPT_MULTI_PATH
5071     if (points) free(points);
5072     if (opvp_p) free(opvp_p);
5073     if (cp_num) free(cp_num);
5074 #endif
5075     return ecode;
5076 }
5077 
5078 /*
5079  * vector do rect
5080  */
5081 static  int
opvp_vector_dorect(gx_device_vector * vdev,fixed x0,fixed y0,fixed x1,fixed y1,gx_path_type_t type)5082 opvp_vector_dorect(
5083     gx_device_vector *vdev,
5084     fixed x0,
5085     fixed y0,
5086     fixed x1,
5087     fixed y1,
5088     gx_path_type_t type)
5089 {
5090     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5091     opvp_result_t r = -1;
5092     int code = -1;
5093     int ecode = 0;
5094     gs_point scale;
5095     opvp_rectangle_t rectangles[1];
5096     _fPoint p;
5097 
5098     /* check page-in */
5099     if (opvp_check_in_page(pdev)) return -1;
5100 
5101     /* begin path */
5102     code = (*vdev_proc(vdev, beginpath))(vdev, type);
5103     if (code) ecode = code;
5104     scale = vdev->scale;
5105 
5106     if (!ecode) {
5107         /* rectangle */
5108         p.x = fixed2float(x0) / scale.x;
5109         p.y = fixed2float(y0) / scale.y;
5110         OPVP_F2FIX(p.x, rectangles[0].p0.x);
5111         OPVP_F2FIX(p.y, rectangles[0].p0.y);
5112         p.x = fixed2float(x1) / scale.x;
5113         p.y = fixed2float(y1) / scale.y;
5114         OPVP_F2FIX(p.x, rectangles[0].p1.x);
5115         OPVP_F2FIX(p.y, rectangles[0].p1.y);
5116 
5117         /* call RectanglePath */
5118         if (apiEntry->opvpRectanglePath) {
5119             r = apiEntry->opvpRectanglePath(printerContext,
5120                                    1,
5121                                    rectangles);
5122         }
5123         if (r != OPVP_OK) {
5124             ecode = -1;
5125         }
5126     }
5127 
5128     /* end path */
5129     if (!ecode) {
5130         code = (*vdev_proc(vdev, endpath))(vdev, type);
5131         if (code) ecode = code;
5132     }
5133 
5134     /* fallback */
5135     if (ecode) return gdev_vector_dorect(vdev,x0,y0,x1,y1,type);
5136 
5137     return ecode;
5138 }
5139 
5140 /*
5141  * begin path
5142  */
5143 static  int
opvp_beginpath(gx_device_vector * vdev,gx_path_type_t type)5144 opvp_beginpath(gx_device_vector *vdev, gx_path_type_t type)
5145 {
5146     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5147     opvp_result_t r = -1;
5148     int ecode = 0;
5149 
5150     /* check page-in */
5151     if (opvp_check_in_page(pdev)) return -1;
5152 
5153     /* check clip-path */
5154     if (type & gx_path_type_clip) {
5155         if (apiEntry->opvpResetClipPath)
5156         apiEntry->opvpResetClipPath(printerContext);
5157     }
5158 
5159     /* call NewPath */
5160     if (apiEntry->opvpNewPath) {
5161         r = apiEntry->opvpNewPath(printerContext);
5162     }
5163     if (r != OPVP_OK) {
5164         ecode = -1;
5165     }
5166 
5167     return ecode;
5168 }
5169 
5170 /*
5171  * move to
5172  */
5173 static  int
opvp_moveto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x1,floatp y1,gx_path_type_t type)5174 opvp_moveto(
5175     gx_device_vector *vdev,
5176     floatp x0,
5177     floatp y0,
5178     floatp x1,
5179     floatp y1,
5180     gx_path_type_t type)
5181 {
5182     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5183     opvp_result_t r = -1;
5184     int ecode = 0;
5185     opvp_point_t p;
5186 
5187     /* check page-in */
5188     if (opvp_check_in_page(pdev)) return -1;
5189 
5190     /* call SetCurrentPoint */
5191     OPVP_F2FIX(x1, p.x);
5192     OPVP_F2FIX(y1, p.y);
5193     if (apiEntry->opvpSetCurrentPoint) {
5194         r = apiEntry->opvpSetCurrentPoint(printerContext, p.x, p.y);
5195     }
5196     if (r != OPVP_OK) {
5197         ecode = -1;
5198     }
5199 
5200     return ecode;
5201 }
5202 
5203 /*
5204  * line to
5205  */
5206 static  int
opvp_lineto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x1,floatp y1,gx_path_type_t type)5207 opvp_lineto(
5208     gx_device_vector *vdev,
5209     floatp x0,
5210     floatp y0,
5211     floatp x1,
5212     floatp y1,
5213     gx_path_type_t type)
5214 {
5215     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5216     opvp_result_t r = -1;
5217     int ecode = 0;
5218     opvp_point_t points[1];
5219 
5220     /* check page-in */
5221     if (opvp_check_in_page(pdev)) return -1;
5222 
5223     /* point */
5224     OPVP_F2FIX(x1, points[0].x);
5225     OPVP_F2FIX(y1, points[0].y);
5226 
5227     /* call LinePath */
5228     if (apiEntry->opvpLinePath) {
5229         r = apiEntry->opvpLinePath(printerContext, OPVP_PATHOPEN, 1, points);
5230     }
5231     if (r != OPVP_OK) {
5232         ecode = -1;
5233     }
5234 
5235     return ecode;
5236 }
5237 
5238 /*
5239  * curve to
5240  */
5241 static  int
opvp_curveto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x1,floatp y1,floatp x2,floatp y2,floatp x3,floatp y3,gx_path_type_t type)5242 opvp_curveto(
5243     gx_device_vector *vdev,
5244     floatp x0,
5245     floatp y0,
5246     floatp x1,
5247     floatp y1,
5248     floatp x2,
5249     floatp y2,
5250     floatp x3,
5251     floatp y3,
5252     gx_path_type_t type)
5253 {
5254     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5255     opvp_result_t r = -1;
5256     int ecode = 0;
5257     int npoints[2];
5258     opvp_point_t points[4];
5259 
5260     /* check page-in */
5261     if (opvp_check_in_page(pdev)) return -1;
5262 
5263     /* points */
5264     npoints[0] = 4;
5265     npoints[1] = 0;
5266     OPVP_F2FIX(x0, points[0].x);
5267     OPVP_F2FIX(y0, points[0].y);
5268     OPVP_F2FIX(x1, points[1].x);
5269     OPVP_F2FIX(y1, points[1].y);
5270     OPVP_F2FIX(x2, points[2].x);
5271     OPVP_F2FIX(y2, points[2].y);
5272     OPVP_F2FIX(x3, points[3].x);
5273     OPVP_F2FIX(y3, points[3].y);
5274 
5275     /* call BezierPath */
5276     if (apiEntry->opvpBezierPath) {
5277         r = apiEntry->opvpBezierPath(printerContext,
5278                             3,
5279                             &(points[1])
5280                             );
5281     }
5282     if (r != OPVP_OK) {
5283         ecode = -1;
5284     }
5285 
5286     return ecode;
5287 }
5288 
5289 /*
5290  * close path
5291  */
5292 static  int
opvp_closepath(gx_device_vector * vdev,floatp x,floatp y,floatp x_start,floatp y_start,gx_path_type_t type)5293 opvp_closepath(
5294     gx_device_vector *vdev,
5295     floatp x,
5296     floatp y,
5297     floatp x_start,
5298     floatp y_start,
5299     gx_path_type_t type)
5300 {
5301     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5302     opvp_result_t r = -1;
5303     int ecode = 0;
5304     opvp_point_t points[1];
5305 
5306     /* check page-in */
5307     if (opvp_check_in_page(pdev)) return -1;
5308 
5309     /* point */
5310     OPVP_F2FIX(x_start, points[0].x);
5311     OPVP_F2FIX(y_start, points[0].y);
5312 
5313     /* call LinePath */
5314     if (apiEntry->opvpLinePath) {
5315         r = apiEntry->opvpLinePath(printerContext, OPVP_PATHCLOSE, 1, points);
5316     }
5317     if (r != OPVP_OK) {
5318         ecode = -1;
5319     }
5320 
5321     return ecode;
5322 }
5323 
5324 /*
5325  * end path
5326  */
5327 static  int
opvp_endpath(gx_device_vector * vdev,gx_path_type_t type)5328 opvp_endpath(gx_device_vector *vdev, gx_path_type_t type)
5329 {
5330     gx_device_opvp *pdev = (gx_device_opvp *)vdev;
5331     opvp_result_t r = -1;
5332     int ecode = 0;
5333 
5334     /* check page-in */
5335     if (opvp_check_in_page(pdev)) return -1;
5336 
5337     /* call EndPath */
5338     if (apiEntry->opvpEndPath) {
5339         r = apiEntry->opvpEndPath(printerContext);
5340     }
5341     if (r != OPVP_OK) {
5342         ecode = -1;
5343     }
5344 
5345     if (type & gx_path_type_fill) {
5346         /* fill mode */
5347         if (type & gx_path_type_even_odd) {
5348             /* call SetFillMode */
5349             if (apiEntry->opvpSetFillMode) {
5350                 r = apiEntry->opvpSetFillMode(
5351                    printerContext,
5352                    OPVP_FILLMODE_EVENODD
5353                 );
5354             }
5355             if (r != OPVP_OK) {
5356                 ecode = -1;
5357             }
5358         } else {
5359             /* call SetFillMode */
5360             if (apiEntry->opvpSetFillMode) {
5361                 r = apiEntry->opvpSetFillMode(
5362                    printerContext,
5363                    OPVP_FILLMODE_WINDING
5364                 );
5365             }
5366             if (r != OPVP_OK) {
5367                 ecode = -1;
5368             }
5369         }
5370 
5371         if (type & gx_path_type_stroke) {
5372             /* call StrokeFillPath */
5373             if (apiEntry->opvpStrokeFillPath) {
5374                 r = apiEntry->opvpStrokeFillPath(printerContext);
5375             }
5376             if (r != OPVP_OK) {
5377                 ecode = -1;
5378             }
5379         } else {
5380             /* call FillPath */
5381             if (apiEntry->opvpFillPath) {
5382                 r = apiEntry->opvpFillPath(printerContext);
5383             }
5384             if (r != OPVP_OK) {
5385                 ecode = -1;
5386             }
5387         }
5388     } else if (type & gx_path_type_clip) {
5389         /* call SetClipPath */
5390         if (apiEntry->opvpSetClipPath) {
5391             r = apiEntry->opvpSetClipPath(
5392                printerContext,
5393                (type & gx_path_type_even_odd
5394                             ? OPVP_CLIPRULE_EVENODD
5395                             : OPVP_CLIPRULE_WINDING));
5396         }
5397         if (r != OPVP_OK) {
5398             ecode = -1;
5399         }
5400     } else if (type & gx_path_type_stroke) {
5401         /* call StrokePath */
5402         if (apiEntry->opvpStrokePath) {
5403             r = apiEntry->opvpStrokePath(printerContext);
5404         }
5405         if (r != OPVP_OK) {
5406             ecode = -1;
5407         }
5408     }
5409 
5410     return ecode;
5411 }
5412