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