/* Copyright (C) EPSON KOWA Corp. 2000, 2001, 2002, 2003 Ghostscript printer driver for EPSON ESC/Page This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute this software, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with this software so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /*$Id: gdevesmv.c,v 1.1 2004/05/17 05:25:19 ishii Exp $ */ /* Vector Version of ESC/Page driver */ /* 謝辞:大森紀人氏の gdevl4v.cを参考にさせてもらいました。 */ /* ○Ghostscript 5.10/5.50 のバグについて Ghostscript 5.10/5.50 の Vector driver の setlinewidth 関数には バグがあります。本来スケールが変更されるにしたがって線の太さも変更され なければなりませんが、Ghostscript 5.10/5.50 ではスケールを考慮するのを 忘れています。 このドライバはそのバグを回避するためにスケールを自分で処理しています。 */ #include "math_.h" #include "gx.h" #include "gserrors.h" #include "gsmatrix.h" #include "gsparam.h" #include "gxdevice.h" #include "gscspace.h" #include "gsutil.h" #include "gdevvec.h" #include "spprint.h" #if GS_VERSION_MAJOR == 5 #include "gdevpstr.h" #endif #include "ghost.h" #include "gzstate.h" #include "imemory.h" #include "igstate.h" #include "gdevescv.h" #include "gspath.h" #include "gzpath.h" #include #include #include /* ---------------- Device definition ---------------- */ /* Device procedures */ private dev_proc_open_device(esmv_open); private dev_proc_output_page(esmv_output_page); private dev_proc_close_device(esmv_close); private dev_proc_copy_mono(esmv_copy_mono); private dev_proc_copy_color(esmv_copy_color); private dev_proc_put_params(esmv_put_params); private dev_proc_get_params(esmv_get_params); private dev_proc_fill_mask(esmv_fill_mask); private dev_proc_begin_image(esmv_begin_image); #define X_DPI 600 #define Y_DPI 600 typedef struct gx_device_esmv_s { gx_device_vector_common; bool manualFeed; /* Use manual feed */ int cassetFeed; /* Input Casset */ bool RITOff; /* RIT Control */ bool Collate; /* 印刷部数 */ int toner_density; /* トナー濃度 */ bool toner_saving; /* トナーセーブ */ int prev_paper_size; int prev_paper_width; int prev_paper_height; int prev_num_copies; /* */ int prev_feed_mode; int orientation; /* 方向 */ bool faceup; /* フェイス指定 */ int MediaType; /* 紙種 */ bool first_page; bool Duplex; /* 両面印刷 */ bool Tumble; /* とじ方向 */ int ncomp; /* */ int MaskReverse; /* 反転処理 */ int MaskState; /* */ bool c4map; /* 4bit ColorMap */ bool c8map; /* 8bit ColorMap */ int prev_x; int prev_y; gx_color_index prev_color; gx_color_index current_color; /* Current Color */ floatp lwidth; long cap; long join; long reverse_x; long reverse_y; gs_matrix xmat; int bx, by; int w, h; int roll; float sx, sy; long dd; } gx_device_esmv; gs_public_st_suffix_add0_final(st_device_esmv, gx_device_esmv, "gx_device_esmv", device_esmv_enum_ptrs, device_esmv_reloc_ptrs, gx_device_finalize, st_device_vector); #define esmv_device_full_body(dtype, pprocs, dname, stype, w, h, xdpi, ydpi, \ ncomp, depth, mg, mc, dg, dc, lm, bm, rm, tm)\ std_device_part1_(dtype, pprocs, dname, stype, open_init_closed),\ dci_values(ncomp, depth, mg, mc, dg, dc),\ std_device_part2_(w, h, xdpi, ydpi),\ offset_margin_values(-lm * xdpi / 72.0, -tm * ydpi / 72.0, 0. / (MMETER_PER_INCH / POINT), 0, 0, 5. / (MMETER_PER_INCH / POINT)), \ std_device_part3_() #define esmv_device_body(name) \ esmv_device_full_body(gx_device_esmv, 0, name, \ &st_device_esmv,\ /* width & height */ ESCPAGE_DEFAULT_WIDTH, ESCPAGE_DEFAULT_HEIGHT,\ /* default resolution */ X_DPI, Y_DPI,\ /* color info */ /* 3, 24, 255, 255, 256, 256,*/\ /* color info */ 1, 8, 255, 255, 256, 256,\ ESCPAGE_LEFT_MARGIN_DEFAULT,\ ESCPAGE_BOTTOM_MARGIN_DEFAULT,\ ESCPAGE_RIGHT_MARGIN_DEFAULT,\ ESCPAGE_TOP_MARGIN_DEFAULT) #define esmv_procs \ {\ esmv_open, /* open_device */\ gx_default_get_initial_matrix, /* get_initial_matrix */\ NULL, /* sync_output */\ esmv_output_page, /* output_page */\ esmv_close, /* close_device */\ /* gx_default_rgb_map_rgb_color, */ /* map_rgb_color */\ gx_default_gray_map_rgb_color,\ /* gx_default_rgb_map_color_rgb, */ /* map_color_rgb */\ gx_default_gray_map_color_rgb,\ gdev_vector_fill_rectangle, /* fill_rectangle */\ NULL, /* tile_rectangle */\ esmv_copy_mono, /* dev_t_proc_copy_mono */\ esmv_copy_color, /* dev_t_proc_copy_color */\ NULL, /* draw_line */\ NULL, /* get_bits */\ esmv_get_params, /* dev_t_proc_get_params */\ esmv_put_params, /* dev_t_proc_put_params */\ NULL, /* map_cmyk_color */\ NULL, /* get_xfont_procs */\ NULL, /* get_xfont_device */\ NULL, /* map_rgb_alpha_color */\ gx_page_device_get_page_device, /* dev_t_proc_get_page_device */\ NULL, /* get_alpha_bits */\ NULL, /* copy_alpha */\ NULL, /* get_band */\ NULL, /* copy_rop */\ gdev_vector_fill_path, /* fill_path */\ gdev_vector_stroke_path, /* stroke_path */\ esmv_fill_mask, /* fill_mask */\ gdev_vector_fill_trapezoid, /* fill_trapezoid */\ gdev_vector_fill_parallelogram, /* fill_parallelogram */\ gdev_vector_fill_triangle, /* fill_triangle */\ NULL, /****** WRONG ******/ /* draw_thin_line */\ esmv_begin_image, /* begin_image */\ NULL, /* image_data */\ NULL, /* end_image */\ NULL, /* strip_tile_rectangle */\ NULL /******strip_copy_rop******/\ } #define esmv_init_code \ vector_initial_values,\ ESCPAGE_MANUALFEED_DEFAULT,\ ESCPAGE_CASSETFEED_DEFAULT,\ ESCPAGE_RIT_DEFAULT, /* RIT */\ FALSE, /* Collate */\ 0, /* toner_density */\ FALSE, /* toner_saving */\ 0, 0, 0, 0, -1,\ 0, /* orientation */\ ESCPAGE_FACEUP_DEFAULT,\ ESCPAGE_MEDIATYPE_DEFAULT,\ 0, /* first_page */\ 0, /* Duplex */\ ESCPAGE_TUMBLE_DEFAULT,\ 0, /* ncomp */\ 0, /* MaskReverse */\ 0, /* MaskState */\ TRUE, /* 4bits Color Map */\ TRUE, /* 8bits Color Map */\ 0, /* prev_x */\ 0, /* prev_y */\ 0, /* prev_color */\ 0, /* current_color */\ 3, /* lwidth */\ 0, /* cap */\ 3, /* join */\ 0,0, /* reverse x, y */\ {}, /* matrix */\ 0,0, /* x, y */\ 0,0, /* width, hight */\ 0, /* roll */\ 0,0, /* scale x, y */\ 0 /* */ gx_device_esmv far_data gs_lp9000b_device = { esmv_device_body("lp9000b"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp2500_device = { esmv_device_body("lp2500"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp9100_device = { esmv_device_body("lp9100"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp7900_device = { esmv_device_body("lp7900"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp7500_device = { esmv_device_body("lp7500"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp2400_device = { esmv_device_body("lp2400"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8900_device = { esmv_device_body("lp8900"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp7700_device = { esmv_device_body("lp7700"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp2200_device = { esmv_device_body("lp2200"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp9400_device = { esmv_device_body("lp9400"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8700_device = { esmv_device_body("lp8700"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8100_device = { esmv_device_body("lp8100"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp1800_device = { esmv_device_body("lp1800"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp9600_device = { esmv_device_body("lp9600"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp9300_device = { esmv_device_body("lp9300"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8600_device = { esmv_device_body("lp8600"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8600f_device = { esmv_device_body("lp8600f"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8400f_device = { esmv_device_body("lp8400f"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp8300f_device = { esmv_device_body("lp8300f"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp1900_device = { esmv_device_body("lp1900"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_lp9600s_device = { esmv_device_body("lp9600s"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl6100_device = { esmv_device_body("epl6100"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl5900_device = { esmv_device_body("epl5900"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl5800_device = { esmv_device_body("epl5800"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl2050_device = { esmv_device_body("epl2050"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl2050p_device = { esmv_device_body("epl2050p"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl2120_device = { esmv_device_body("epl2120"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl2500_device = { esmv_device_body("epl2500"), esmv_procs, esmv_init_code }; gx_device_esmv far_data gs_epl2750_device = { esmv_device_body("epl2750"), esmv_procs, esmv_init_code }; /* Vector device implementation */ #if GS_VERSION_MAJOR >= 8 private int esmv_beginpage(gx_device_vector * vdev); private int esmv_setfillcolor(gx_device_vector * vdev, const gx_drawing_color * pdc); private int esmv_setstrokecolor(gx_device_vector * vdev, const gx_drawing_color * pdc); private int esmv_setdash(gx_device_vector * vdev, const float *pattern, uint count, floatp offset); private int esmv_setflat(gx_device_vector * vdev, floatp flatness); private int esmv_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop, gs_logical_operation_t diff); #else private int esmv_beginpage(P1(gx_device_vector * vdev)); private int esmv_setfillcolor(P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); private int esmv_setstrokecolor(P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); private int esmv_setdash(P4(gx_device_vector * vdev, const float *pattern, uint count, floatp offset)); private int esmv_setflat(P2(gx_device_vector * vdev, floatp flatness)); private int esmv_setlogop(P3(gx_device_vector * vdev, gs_logical_operation_t lop, gs_logical_operation_t diff)); #endif private int esmv_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, gx_path_type_t type); private int esmv_vector_dopath(gx_device_vector * vdev, const gx_path * ppath, gx_path_type_t type); #if GS_VERSION_MAJOR >= 8 private int esmv_beginpath(gx_device_vector * vdev, gx_path_type_t type); private int esmv_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, gx_path_type_t type); private int esmv_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, gx_path_type_t type); private int esmv_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); private int esmv_closepath(gx_device_vector * vdev, floatp x, floatp y, floatp x_start, floatp y_start, gx_path_type_t type); private int esmv_endpath(gx_device_vector * vdev, gx_path_type_t type); #else private int esmv_beginpath(P2(gx_device_vector * vdev, gx_path_type_t type)); private int esmv_moveto(P6(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, gx_path_type_t type)); private int esmv_lineto(P6(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, gx_path_type_t type)); private int esmv_curveto(P10(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)); private int esmv_closepath(P6(gx_device_vector * vdev, floatp x, floatp y, floatp x_start, floatp y_start, gx_path_type_t type)); private int esmv_endpath(P2(gx_device_vector * vdev, gx_path_type_t type)); #endif private int esmv_setlinewidth(gx_device_vector * vdev, floatp width); private int esmv_setlinecap(gx_device_vector * vdev, gs_line_cap cap); private int esmv_setlinejoin(gx_device_vector * vdev, gs_line_join join); private int esmv_setmiterlimit(gx_device_vector * vdev, floatp limit); private void esmv_write_begin(gx_device *, int, int, int, int, int, int, int, int); private void esmv_write_data(gx_device *, int, char *, int, int, int); private void esmv_write_end(gx_device *, int); private const gx_device_vector_procs esmv_vector_procs = { /* Page management */ esmv_beginpage, /* Imager state */ esmv_setlinewidth, esmv_setlinecap, esmv_setlinejoin, esmv_setmiterlimit, esmv_setdash, esmv_setflat, esmv_setlogop, /* Other state */ esmv_setfillcolor, /* fill & stroke colors are the same */ esmv_setstrokecolor, /* Paths */ esmv_vector_dopath, esmv_vector_dorect, esmv_beginpath, esmv_moveto, esmv_lineto, esmv_curveto, esmv_closepath, esmv_endpath }; /* ---------------- Utilities ---------------- */ /* Put a string on a stream. This function is copy of `pputs' in gdevpstr.c */ private int lputs(stream * s, const char *str) { uint len = strlen(str); uint used; int status; status = sputs(s, (const byte *)str, len, &used); return (status >= 0 && used == len ? 0 : EOF); } /* Write a string on a stream. */ private void put_bytes(stream * s, const byte * data, uint count) { uint used; sputs(s, data, count, &used); } private int esmv_range_check(gx_device * dev) { int width = dev->MediaSize[0]; int height = dev->MediaSize[1]; int xdpi = dev->x_pixels_per_inch; int ydpi = dev->y_pixels_per_inch; /* Paper Size Check */ if (width <= height) { /* portrait */ if ((width < ESCPAGE_WIDTH_MIN || width > ESCPAGE_WIDTH_MAX || height < ESCPAGE_HEIGHT_MIN || height > ESCPAGE_HEIGHT_MAX) && !(width == ESCPAGE_LEDGER_WIDTH && height == ESCPAGE_LEDGER_HEIGHT)) return_error(gs_error_rangecheck); } else { /* landscape */ if ((width < ESCPAGE_HEIGHT_MIN || width > ESCPAGE_HEIGHT_MAX || height < ESCPAGE_WIDTH_MIN || height > ESCPAGE_WIDTH_MAX) && !(width == ESCPAGE_LEDGER_HEIGHT && height == ESCPAGE_LEDGER_WIDTH)) return_error(gs_error_rangecheck); } /* Resolution Check */ if (xdpi != ydpi) return_error(gs_error_rangecheck); else { if ((xdpi < ESCPAGE_DPI_MIN || xdpi > ESCPAGE_DPI_MAX) && xdpi != ESCPAGE_DPI_SUPERFINE) return_error(gs_error_rangecheck); } return 0; } /* ---------------- Vector device implementation ---------------- */ int esmv_vector_dopath(gx_device_vector * vdev, const gx_path * ppath, gx_path_type_t type) { bool do_close = (type & gx_path_type_stroke) != 0; gs_fixed_rect rect; gs_point scale; double x_start = 0, y_start = 0, x_prev = 0, y_prev = 0; bool first = true; gs_path_enum cenum; int code; stream *s = gdev_vector_stream(vdev); char obuf[128]; if (gx_path_is_rectangle(ppath, &rect)) return (*vdev_proc(vdev, dorect)) (vdev, rect.p.x, rect.p.y, rect.q.x, rect.q.y, type); scale = vdev->scale; code = (*vdev_proc(vdev, beginpath)) (vdev, type); gx_path_enum_init(&cenum, ppath); for (;;) { double x, y; fixed vs[6]; int pe_op, cnt; segment *pseg; pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); sw:switch (pe_op) { case 0: /* done */ return (*vdev_proc(vdev, endpath)) (vdev, type); case gs_pe_moveto: x = fixed2float(vs[0]) / scale.x; y = fixed2float(vs[1]) / scale.y; /* サブパス開始命令 p1 */ (void)sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x, (int)y); lputs(s, obuf); if (first) x_start = x, y_start = y, first = false; break; case gs_pe_lineto: cnt = 1; for (pseg = cenum.pseg; pseg != 0 && pseg->type == s_line; cnt++, pseg = pseg->next); (void)sprintf(obuf, ESC_GS "0;%d", cnt); lputs(s, obuf); do { (void)sprintf(obuf, ";%d;%d", (int)(fixed2float(vs[0]) / scale.x), (int)(fixed2float(vs[1]) / scale.y)); lputs(s, obuf); pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); } while (pe_op == gs_pe_lineto); /* パス・ポリライン命令 */ lputs(s, "lnpG"); goto sw; case gs_pe_curveto: cnt = 1; for (pseg = cenum.pseg; pseg != 0 && pseg->type == s_curve; cnt++, pseg = pseg->next); (void)sprintf(obuf, ESC_GS "0;%d", cnt * 3); lputs(s, obuf); do { (void)sprintf(obuf, ";%d;%d;%d;%d;%d;%d", (int)(fixed2float(vs[0]) / scale.x), (int)(fixed2float(vs[1]) / scale.y), (int)(fixed2float(vs[2]) / scale.x), (int)(fixed2float(vs[3]) / scale.y), (int)(fixed2float(vs[4]) / scale.x), (int)(fixed2float(vs[5]) / scale.y)); lputs(s, obuf); pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); } while (pe_op == gs_pe_curveto); /* ベジェ曲線 */ lputs(s, "bzpG"); goto sw; case gs_pe_closepath: x = x_start, y = y_start; if (do_close) { lputs(s, ESC_GS "clpG"); break; } pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); if (pe_op != 0) { lputs(s, ESC_GS "clpG"); if (code < 0) return code; goto sw; } return (*vdev_proc(vdev, endpath)) (vdev, type); default: /* can't happen */ return_error(gs_error_unknownerror); } if (code < 0) return code; x_prev = x, y_prev = y; } } int esmv_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, gx_path_type_t type) { int code; char obuf[128]; gs_point scale; stream *s = gdev_vector_stream(vdev); code = (*vdev_proc(vdev, beginpath))(vdev, type); if (code < 0) return code; scale = vdev->scale; (void)sprintf(obuf, ESC_GS "0;%d;%d;%d;%d;0;0rrpG", (int)(fixed2float(x0) / scale.x), (int)(fixed2float(y0) / scale.y), (int)(fixed2float(x1) / scale.x), (int)(fixed2float(y1) / scale.y)); lputs(s, obuf); #if 0 /* Ghostscript 側のバグで closepath を呼んでいないので処理を会わせる。 */ /* 本来は (*vdev_proc(vdev, closepath))() を呼ぶべき */ lputs(s, ESC_GS "clpG"); #endif return (*vdev_proc(vdev, endpath))(vdev, type); } /* ---------- */ typedef struct { int width; /* paper width (unit: point) */ int height; /* paper height (unit: point) */ int escpage; /* number of papersize in ESC/PAGE */ char *name; /* Paper Name */ } EPaperTable; private const EPaperTable ePaperTable[24] = { {933, 1369, 72, "A3PLUS"}, /* A3 NOBI */ {842, 1190, 13, "A3"}, /* A3 */ {595, 842, 14, "A4"}, /* A4 */ {421, 595, 15, "A5"}, /* A5 */ {709, 1002, 24, "B4"}, /* B4 */ {729, 1032, 24, "B4"}, /* B4 JIS */ {516, 729, 25, "B5"}, /* B5 JIS */ {612, 792, 30, "LT"}, /* Letter */ {396, 612, 31, "HLT"}, /* Half Letter */ {612, 1008, 32, "LGL"}, /* Legal */ {522, 756, 33, "EXE"}, /* Executive */ {612, 936, 34, "GLG"}, /* Government Letter */ /* LPD.1. */ {576, 756, 35, "GLT"}, /* Government Legal */ /* LPD.1. */ {792, 1224, 36, "B"}, /* Ledger */ {593, 935, 37, "F4"}, /* F4 */ {284, 419, 38, "POSTCARD"}, /* PostCard */ {298, 666, 64, "YOU4"}, /* Japanese Envelope You4 */ {279, 540, 80, "MON"}, /* Monarch */ {297, 684, 81, "C10"}, /* Commercial 10 */ {312, 624, 90, "DL"}, /* DL */ {459, 649, 91, "C5"}, /* Envelope C5 */ {501, 709, 99, "IB5"}, /* Envelope ISO B5 */ {0, 0, -1, NULL} /* Undefined */ }; private int esmv_beginpage(gx_device_vector * vdev) { gx_device_esmv *const pdev = (gx_device_esmv *)vdev; /* gdev_vector_stream は使用禁止 */ stream *s = vdev->strm; char ebuf[1024]; int w, h; EPaperTable *pt; int MaxRes; int Local; int Duplex; int FaceUp; if (pdev -> first_page) { if (strcmp(pdev->dname, "lp9600s") == 0 || \ strcmp(pdev->dname, "lp9600") == 0 || \ strcmp(pdev->dname, "lp9400") == 0 || \ strcmp(pdev->dname, "lp9300") == 0 || \ strcmp(pdev->dname, "lp9100") == 0 || \ strcmp(pdev->dname, "lp9000b") == 0 || \ strcmp(pdev->dname, "lp8900") == 0 || \ strcmp(pdev->dname, "lp8600f") == 0 || \ strcmp(pdev->dname, "lp8600") == 0 || \ strcmp(pdev->dname, "lp8400f") == 0 || \ strcmp(pdev->dname, "lp8300f") == 0 || \ strcmp(pdev->dname, "lp8100") == 0 || \ strcmp(pdev->dname, "lp7900") == 0 || \ strcmp(pdev->dname, "lp7700") == 0 || \ strcmp(pdev->dname, "lp7500") == 0) { MaxRes = RES600; Local = JPN; Duplex = TRUE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "lp1800") == 0) { MaxRes = RES600; Local = JPN; Duplex = FALSE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "lp8700") == 0) { MaxRes = RES1200; Local = JPN; Duplex = TRUE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "lp2200") == 0 || \ strcmp(pdev->dname, "lp2500") == 0 || \ strcmp(pdev->dname, "lp2400") == 0 || \ strcmp(pdev->dname, "lp1900") == 0) { MaxRes = RES1200; Local = JPN; Duplex = FALSE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "epl5900") == 0 || \ strcmp(pdev->dname, "epl6100") == 0 || \ strcmp(pdev->dname, "epl5800") == 0) { MaxRes = RES1200; Local = ENG; Duplex = FALSE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "epl2050") == 0 || \ strcmp(pdev->dname, "epl2050p") == 0 || \ strcmp(pdev->dname, "epl2120") == 0) { MaxRes = RES1200; Local = ENG; Duplex = TRUE; FaceUp = FALSE; } else if (strcmp(pdev->dname, "epl2750") == 0 || \ strcmp(pdev->dname, "epl2500") == 0) { MaxRes = RES600; Local = ENG; Duplex = TRUE; FaceUp = FALSE; } else { MaxRes = RES600; Local = JPN; Duplex = FALSE; FaceUp = FALSE; } lputs(s, "\033\001@EJL \012@EJL SJ ID=\"Ghostscript\"\012"); lputs(s, "@EJL SE LA=ESC/PAGE\012"); lputs(s, "@EJL SET"); /* Resolusion */ if (vdev->x_pixels_per_inch == 1200){ if (MaxRes == 1200){ lputs(s, " RS=1200"); } else { lputs(s, " RS=FN"); } } else if (vdev->x_pixels_per_inch == 600) { lputs(s, " RS=FN"); } else { lputs(s, " RS=QK"); } /* Output Unit */ if ((pdev->faceup && FaceUp) || (pdev->MediaType && FaceUp)) { lputs(s, " OU=FU"); } else { lputs(s, " OU=FD"); } /* Paper unit */ if (pdev->MediaType){ if (Local == ENG){ lputs(s, " PU=1"); } else { lputs(s, " PU=15"); } }else{ if (pdev->manualFeed) { if (Local == ENG){ lputs(s, " PU=1"); } else { lputs(s, " PU=15"); } } else if (pdev->cassetFeed) { (void)sprintf(ebuf, " PU=%d", pdev->cassetFeed); lputs(s, ebuf); } else { lputs(s, " PU=AU"); } } if (Duplex && pdev->Duplex) { /* 両面印刷指定 */ lputs(s, " DX=ON"); /* とじ方向 */ if (pdev->Tumble) { lputs(s, " BD=SE"); } else { lputs(s, " BD=LE"); } } else { /* 両面印刷off */ lputs(s, " DX=OFF"); } /* 印刷部数 */ if (pdev->NumCopies) { if (pdev->NumCopies >= 1000) { pdev->NumCopies = 999; } if (pdev->Collate) { /* QT を指定した場合 CO は 1 */ (void)sprintf(ebuf, " QT=%d CO=1", pdev->NumCopies); } else { /* QT を指定しなかった場合 QT は 1 */ (void)sprintf(ebuf, " QT=1 CO=%d", pdev->NumCopies); } lputs(s, ebuf); } else { lputs(s, " QT=1 CO=1"); } if (pdev->toner_density) { (void)sprintf(ebuf, " DL=%d", pdev->toner_density); lputs(s, ebuf); } if (pdev->orientation) { lputs(s, " OR=LA"); } if (pdev->toner_saving) { lputs(s, " SN=ON"); } if (pdev->RITOff) { lputs(s, " RI=OFF"); } else { lputs(s, " RI=ON"); } if (pdev->MediaType == 1) { lputs(s, " PK=TH"); } else if (pdev->MediaType == 2) { lputs(s, " PK=TR"); } else { lputs(s, " PK=NM"); } if (pdev->MediaSize[0] < pdev->MediaSize[1]) { w = pdev->MediaSize[0]; h = pdev->MediaSize[1]; } else { w = pdev->MediaSize[1]; h = pdev->MediaSize[0]; } for (pt = ePaperTable; pt->escpage > 0; pt++) if (pt->width == w && pt->height == h) break; if (pt->name == NULL) { lputs(s, " PS=A4"); } else { (void)sprintf(ebuf, " PS=%s", pt->name); lputs(s, ebuf); } lputs(s, " ZO=OFF EC=ON SZ=OFF SL=YES TO=0.0MM LO=0.0MM\012"); lputs(s, "@EJL EN LA=ESC/PAGE\012"); #define START_CODE1 ESC_GS "1tsE" ESC_GS "1owE" ESC_GS "0alfP" ESC_GS "0affP" ESC_GS "0;0;0clfP" ESC_GS "0pmP" ESC_GS "1024ibI" ESC_GS "2cmE" ESC_GS "0bcI" ESC_GS "1;10mlG" #define STRAT_CODE ESC_GS "1mmE" ESC_GS "1csE" lputs(s, ESC_GS "rhE"); lputs(s, STRAT_CODE); if (vdev->x_pixels_per_inch == 1200) { /* 1200 dpi */ lputs(s, ESC_GS "0;0.06muE"); lputs(s, ESC_GS "1;45;156htmE"); lputs(s, ESC_GS "9;1200;1200drE" ESC_GS "2;1200;1200drE" ESC_GS "1;1200;1200drE" ESC_GS "0;1200;1200drE"); lputs(s, ESC_GS "1;1;raE"); } else if (vdev->x_pixels_per_inch == 600) { /* 600 dpi */ lputs(s, ESC_GS "0;0.12muE"); lputs(s, ESC_GS "1;45;106htmE"); lputs(s, ESC_GS "9;600;600drE" ESC_GS "2;600;600drE" ESC_GS "1;600;600drE" ESC_GS "0;600;600drE"); } else { /* 300 dpi */ lputs(s, ESC_GS "0;0.24muE"); lputs(s, ESC_GS "1;45;71htmE"); lputs(s, ESC_GS "9;300;300drE" ESC_GS "2;300;300drE" ESC_GS "1;300;300drE" ESC_GS "0;300;300drE"); } lputs(s, START_CODE1); lputs(s, ESC_GS "0sarG"); /* 絶対座標指定 */ /* lputs(s, ESC_GS "1owE");*/ } return 0; } private int esmv_setlinewidth(gx_device_vector * vdev, floatp width) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; char obuf[64]; #if GS_VERSION_MAJOR == 5 /* Scale を掛けているのは, Ghostscript 5.10/5.50 のバグのため */ floatp xscale, yscale; xscale = fabs(igs->ctm.xx); yscale = fabs(igs->ctm.xy); if (xscale == 0 || yscale > xscale) /* if portrait */ width = ceil(width * yscale); else width = ceil(width * xscale); #endif if (width < 1) width = 1; /* ESC/Page では線幅/終端/接合部の設定は1つのコマンドになっているため保持しておく。 */ pdev -> lwidth = width; (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG", (int)(pdev -> lwidth), (int)(pdev -> cap), (int)(pdev -> join)); lputs(s, obuf); return 0; } private int esmv_setlinecap(gx_device_vector * vdev, gs_line_cap cap) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; char obuf[64]; /* ESC/Page では線幅/終端/接合部の設定は1つのコマンドになっているため保持しておく。 */ pdev -> cap = cap; if (pdev -> cap >= 3) return -1; (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG", (int)(pdev -> lwidth), (int)(pdev -> cap), (int)(pdev -> join)); lputs(s, obuf); return 0; } private int esmv_setlinejoin(gx_device_vector * vdev, gs_line_join join) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; char obuf[64]; /* ESC/Page では線幅/終端/接合部の設定は1つのコマンドになっているため保持しておく。 */ switch (join) { case 0: pdev -> join = 3; /* miter */ break; case 1: pdev -> join = 1; /* round */ break; case 2: pdev -> join = 2; /* bevel */ break; default: return -1; } (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG", (int)(pdev -> lwidth), (int)(pdev -> cap), (int)(pdev -> join)); lputs(s, obuf); return 0; } private int esmv_setmiterlimit(gx_device_vector * vdev, floatp limit) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; char obuf[128]; /* マイターリミット値を設定するには lwG にて 接合部指定(n3) が 3 になっている ** 必要がある。 */ if (pdev -> join != 3) { /* 強制的に接合部指定を行う */ pdev -> join = 3; (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG", (int)(pdev -> lwidth), (int)(pdev -> cap), (int)(pdev -> join)); lputs(s, obuf); } (void)sprintf(obuf, ESC_GS "1;%dmlG", (int)limit); lputs(s, obuf); return 0; } private int esmv_setfillcolor(gx_device_vector * vdev, const gx_drawing_color * pdc) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; gx_color_index color = gx_dc_pure_color(pdc); char obuf[64]; if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck); pdev->current_color = color; (void)sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;0;%dccE" ,color); lputs(s, obuf); if (vdev->x_pixels_per_inch == 1200) { lputs(s, ESC_GS "1;45;156htmE"); } else if (vdev->x_pixels_per_inch == 600) { lputs(s, ESC_GS "1;45;106htmE"); } else { lputs(s, ESC_GS "1;45;71htmE"); } return 0; } private int esmv_setstrokecolor(gx_device_vector * vdev, const gx_drawing_color * pdc) { stream *s = gdev_vector_stream(vdev); gx_device_esmv *const pdev = (gx_device_esmv *) vdev; gx_color_index color = gx_dc_pure_color(pdc); char obuf[64]; if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck); /* if (vdev->color_info.depth == 24) {*/ pdev->current_color = color; (void)sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;1;%dccE" , color); lputs(s, obuf); if (vdev->x_pixels_per_inch == 1200) { lputs(s, ESC_GS "1;45;156htmE"); } else if (vdev->x_pixels_per_inch == 600) { lputs(s, ESC_GS "1;45;106htmE"); } else { lputs(s, ESC_GS "1;45;71htmE"); } return 0; } /* 線種指定命令 */ private int esmv_setdash(gx_device_vector * vdev, const float *pattern, uint count, floatp offset) { stream *s = gdev_vector_stream(vdev); int i; char obuf[64]; #if GS_VERSION_MAJOR == 5 float scale, xscale, yscale; /* Scale を掛けているのは, Ghostscript 5.10/5.50 のバグのため */ xscale = fabs(igs->ctm.xx); yscale = fabs(igs->ctm.xy); if (xscale == 0) /* if portrait */ scale = yscale; else scale = xscale; #endif if (count == 0){ /* 実線 */ lputs(s, ESC_GS "0;0lpG"); return 0; } /* offset が0以外の場合は描画不可として返却 */ if (offset != 0) return -1; if (count) { if (count == 1) { #if GS_VERSION_MAJOR == 5 (void)sprintf(obuf, ESC_GS "1;%d;%ddlG", (int)(pattern[0] * scale / vdev->x_pixels_per_inch + 0.5), (int)(pattern[0] * scale / vdev->x_pixels_per_inch + 0.5)); #else (void)sprintf(obuf, ESC_GS "1;%d;%ddlG", pattern[0], pattern[0]); #endif lputs(s, obuf); } else { /* pattern に0があった場合は描画不可として返却 */ for (i = 0; i < count; ++i) { if (pattern[i] == 0) return -1; } lputs(s, ESC_GS "1"); for (i = 0; i < count; ++i) { #if GS_VERSION_MAJOR == 5 (void)sprintf(obuf, ";%d", (int)(pattern[i] * scale / vdev->x_pixels_per_inch + 0.5)); #else (void)sprintf(obuf, ";%d", pattern[i]); #endif lputs(s, obuf); } lputs(s, "dlG"); } lputs(s, ESC_GS "1;1lpG"); } return 0; } /* パス平滑度指定 */ private int esmv_setflat(gx_device_vector * vdev, floatp flatness) { return 0; } private int esmv_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop, gs_logical_operation_t diff) { /****** SHOULD AT LEAST DETECT SET-0 & SET-1 ******/ return 0; } private int esmv_beginpath(gx_device_vector * vdev, gx_path_type_t type) { stream *s = gdev_vector_stream(vdev); /* パス構築開始命令 */ if (type & gx_path_type_clip) { lputs(s, ESC_GS "1bgpG"); /* クリップ登録 */ } else { lputs(s, ESC_GS "0bgpG"); /* 描画登録 */ } return 0; } private int esmv_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x1, floatp y1, gx_path_type_t type) { stream *s = gdev_vector_stream(vdev); char obuf[64]; /* サブパス開始命令 */ (void)sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x1, (int)y1); lputs(s, obuf); return 0; } private int esmv_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x1, floatp y1, gx_path_type_t type) { stream *s = gdev_vector_stream(vdev); char obuf[64]; (void)sprintf(obuf, ESC_GS "0;1;%d;%dlnpG", (int)x1, (int)y1); lputs(s, obuf); return 0; } private int esmv_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) { stream *s = gdev_vector_stream(vdev); char obuf[128]; /* ベジェ曲線 */ (void)sprintf(obuf, ESC_GS "0;3;%d;%d;%d;%d;%d;%dbzpG", (int)x1, (int)y1, (int)x2, (int)y2, (int)x3, (int)y3); lputs(s, obuf); return 0; } private int esmv_closepath(gx_device_vector * vdev, floatp x, floatp y, floatp x_start, floatp y_start, gx_path_type_t type) { stream *s = gdev_vector_stream(vdev); lputs(s, ESC_GS "clpG"); return 0; } private int esmv_endpath(gx_device_vector * vdev, gx_path_type_t type) { stream *s = gdev_vector_stream(vdev); if (type & gx_path_type_fill || type & gx_path_type_clip) { /* default で処理されるが出力しておく */ lputs(s, ESC_GS "clpG"); } /* パスクローズ */ lputs(s, ESC_GS "enpG"); /* パス描画 */ if (type & gx_path_type_clip) { /* クリップ指定 ** クリップにも gx_path_type_winding_number, gx_path_type_even_odd の判断が ** 必要だと思うが gs 側が付加してこない。 ** とりあえず gx_path_type_even_odd をデフォルトにする。 */ lputs(s, ESC_GS "1;2capG"); } else if (type & gx_path_type_fill) { /* 塗りつぶし規則設定 */ if (type & gx_path_type_even_odd) { /* lputs(s, ESC_GS "0;0;100spE");*/ lputs(s, ESC_GS "0;2drpG"); /* 塗りつぶし描画 */ } else { /* lputs(s, ESC_GS "0;0;100spE");*/ lputs(s, ESC_GS "0;1drpG"); /* 塗りつぶし描画 */ } } else { lputs(s, ESC_GS "0;0drpG"); /* 輪郭線描画 */ } return 0; } /* ---------------- Driver procedures ---------------- */ /* ------ Open/close/page ------ */ /* Open the device. */ private int esmv_open(gx_device * dev) { gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; int code; /* char *error, *path;*/ float width, height; code = esmv_range_check(dev); if (code < 0) return code; vdev->v_memory = dev->memory; /****** VERY WRONG ******/ vdev->vec_procs = &esmv_vector_procs; code = gdev_vector_open_file_bbox(vdev, 512, true); if (code < 0) return code; gdev_vector_init(vdev); pdev->first_page = true; if(pdev->orientation){ pdev->Margins[1] = (pdev->width - pdev->height - \ ESCPAGE_LEFT_MARGIN_DEFAULT * vdev->x_pixels_per_inch / 72.0) * \ X_DPI / vdev->x_pixels_per_inch; width = dev->MediaSize[0]; height = dev->MediaSize[1]; dev->MediaSize[0] = height; dev->MediaSize[1] = width; } return 0; } /* Wrap up ("output") a page. */ private int esmv_output_page(gx_device * dev, int num_copies, int flush) { gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; stream *s = gdev_vector_stream(vdev); /* 線幅,終端処理,接合部処理を初期化しておく */ lputs(s, ESC_GS "3;0;0lwG" ESC_GS "1;10mlG" ESC_FF); sflush(s); vdev->in_page = false; pdev->first_page = false; gdev_vector_reset(vdev); return 0; } private int esmv_close(gx_device *dev) { gx_device_vector *const vdev = (gx_device_vector *) dev; FILE *f = vdev->file; /* 終了処理コードは決め打ち */ (void)fprintf(f, ESC_GS "rhE" "\033\001@EJL \012@EJL EJ \012\033\001@EJL \012"); gdev_vector_close_file(vdev); return 0; } /* Close the device. */ /* Note that if this is being called as a result of finalization, */ /* the stream may no longer exist; but the file will still be open. */ /* ---------------- Get/put parameters ---------------- */ /* Get parameters. */ private int esmv_get_params(gx_device * dev, gs_param_list * plist) { gx_device_esmv *const pdev = (gx_device_esmv *) dev; int code; int ncode; /* gs_param_string pmedia;*/ gs_param_name param_name; code = gdev_vector_get_params(dev, plist); if (code < 0) return code; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_MANUALFEED, &pdev->manualFeed)) < 0) code = ncode; if ((ncode = param_write_int(plist, ESCPAGE_OPTION_CASSETFEED, &pdev->cassetFeed)) < 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_RIT, &pdev->RITOff)) < 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_COLLATE, &pdev->Collate)) < 0) code = ncode; if ((ncode = param_write_int(plist, ESCPAGE_OPTION_TONERDENSITY, &pdev->toner_density)) < 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_LANDSCAPE, &pdev->orientation)) < 0) code = ncode; if ( param_write_bool(plist, ESCPAGE_OPTION_TONERSAVING, &pdev->toner_saving)< 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_DUPLEX, &pdev->Duplex)) < 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_DUPLEX_TUMBLE, &pdev->Tumble)) < 0) code = ncode; if ((ncode = param_write_bool(plist, ESCPAGE_OPTION_FACEUP, &pdev->faceup)) < 0) code = ncode; if ((ncode = param_write_int(plist, ESCPAGE_OPTION_MEDIATYPE, &pdev->MediaType)) < 0) code = ncode; return code; } /* Put parameters. */ private int esmv_put_params(gx_device * dev, gs_param_list * plist) { gx_device_esmv *const pdev = (gx_device_esmv *) dev; int ecode = 0; int code; gs_param_name param_name; gs_param_string pmedia; bool mf = pdev->manualFeed; int cass = pdev->cassetFeed; bool tum = pdev->Tumble; bool collate = pdev->Collate; int toner_density = pdev->toner_density; bool toner_saving = pdev->toner_saving; bool landscape = pdev->orientation; bool faceup = pdev->faceup; bool duplex = pdev->Duplex; bool RITOff = pdev->RITOff; int old_bpp = dev->color_info.depth; int bpp = 0; if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_MANUALFEED), &mf)) < 0) { param_signal_error(plist, param_name, ecode = code); } switch (code = param_read_int(plist, (param_name = ESCPAGE_OPTION_CASSETFEED), &cass)) { case 0: if (cass < -1 || cass > 15) ecode = gs_error_limitcheck; else break; goto casse; default: ecode = code; casse:param_signal_error(plist, param_name, ecode); case 1: break; } if((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_COLLATE), &collate)) < 0) { param_signal_error(plist, param_name, ecode = code); } if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_RIT), &RITOff)) < 0) { param_signal_error(plist, param_name, ecode = code); } switch (code = param_read_string(plist, (param_name = ESCPAGE_OPTION_MEDIATYPE), &pmedia)) { case 0: if (pmedia.size > ESCPAGE_MEDIACHAR_MAX) ecode = gs_error_limitcheck; else { /* Check the validity of ``MediaType'' characters */ if (strcmp(pmedia.data, "TRANS") == 0) { pdev->MediaType = 2; } else if (strcmp(pmedia.data, "THICK") == 0) { pdev->MediaType = 1; } else { ecode = gs_error_rangecheck; goto pmediae; } } break; goto pmediae; default: ecode = code; pmediae:param_signal_error(plist, param_name, ecode); case 1: if(!pdev->MediaType){ pdev->MediaType = 0; pmedia.data = 0; } break; } switch (code = param_read_int(plist, (param_name = ESCPAGE_OPTION_TONERDENSITY), &toner_density)) { case 0: if (toner_density < 0 || toner_density > 5) ecode = gs_error_rangecheck; else break; goto tden; default: ecode = code; tden: param_signal_error(plist, param_name, ecode); case 1: break; } switch (code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_TONERSAVING), &toner_saving)) { case 0: break; default: if ((code = param_read_null(plist, param_name)) == 0) { break; } ecode = code; param_signal_error(plist, param_name, ecode); case 1: break; } if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_DUPLEX), &duplex)) < 0) param_signal_error(plist, param_name, ecode = code); if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_DUPLEX_TUMBLE), &tum)) < 0) param_signal_error(plist, param_name, ecode = code); if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_LANDSCAPE), &landscape)) < 0) param_signal_error(plist, param_name, ecode = code); if ((code = param_read_bool(plist, (param_name = ESCPAGE_OPTION_FACEUP), &faceup)) < 0) { param_signal_error(plist, param_name, ecode = code); } switch (code = param_read_int(plist, (param_name = "BitsPerPixel"), &bpp)) { case 0: if (bpp != 8 && bpp != 24) ecode = gs_error_rangecheck; else break; goto bppe; default: ecode = code; bppe:param_signal_error(plist, param_name, ecode); case 1: break; } if (bpp != 0) { dev->color_info.depth = bpp; dev->color_info.num_components = ((bpp == 8) ? 1 : 3); dev->color_info.max_gray = (bpp > 8 ? 255 : 1000); dev->color_info.max_color = (bpp > 8 ? 255 : 1000); dev->color_info.dither_grays = (bpp > 8 ? 256 : 5); dev->color_info.dither_colors = (bpp > 8 ? 256 : 2); dev_proc(pdev, map_rgb_color) = ((bpp == 8) ? gx_default_gray_map_rgb_color : gx_default_rgb_map_rgb_color); dev_proc(pdev, map_color_rgb) = ((bpp == 8) ? gx_default_gray_map_color_rgb : gx_default_rgb_map_color_rgb); } if (ecode < 0) return ecode; code = gdev_vector_put_params(dev, plist); if (code < 0) return code; pdev->manualFeed = mf; pdev->cassetFeed = cass; pdev->faceup = faceup; pdev->RITOff = RITOff; pdev->orientation = landscape; pdev->toner_density = toner_density; pdev->toner_saving = toner_saving; pdev->Collate = collate; pdev->Duplex = duplex; pdev->Tumble = tum; if (bpp != 0 && bpp != old_bpp && pdev->is_open) return gs_closedevice(dev); return 0; } /* ---------------- Images ---------------- */ private int esmv_copy_mono(gx_device * dev, const byte * data, int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h, gx_color_index zero, gx_color_index one) { gx_device_esmv *const pdev = (gx_device_esmv *) dev; gx_device_vector *const vdev = (gx_device_vector *) dev; stream *s = gdev_vector_stream(vdev); gx_drawing_color color; int code = 0; gx_color_index c_color = 0; char obuf[128]; int depth = 1; if (id != gs_no_id && zero == gx_no_color_index && one != gx_no_color_index && data_x == 0) { gx_drawing_color dcolor; color_set_pure(&dcolor, one); esmv_setfillcolor(vdev, &dcolor); } if (zero == gx_no_color_index) { if (one == gx_no_color_index) return 0; if (pdev->MaskState != 1) { /* lputs(s, ESC_GS "1owE");*/ (void)sprintf(obuf, ESC_GS "1;1;%dccE", c_color); lputs(s, obuf); if (vdev->x_pixels_per_inch == 1200) { lputs(s, ESC_GS "1;45;156htmE"); } else if (vdev->x_pixels_per_inch == 600) { lputs(s, ESC_GS "1;45;106htmE"); } else { lputs(s, ESC_GS "1;45;71htmE"); } pdev->MaskState = 1; } c_color = one; } else if (one == gx_no_color_index) /* 1bit は透明 ビット反転・zero 色に染める */ { if (pdev->MaskState != 1) { /* lputs(s, ESC_GS "1owE");*/ pdev->MaskState = 1; } c_color = zero; } else if (one == vdev->white) { if (pdev->MaskState != 0) { /* lputs(s, ESC_GS "1owE");*/ pdev->MaskState = 0; } c_color = zero; } else { if (pdev->MaskState != 1) { /* lputs(s, ESC_GS "1owE");*/ pdev->MaskState = 1; } color_set_pure(&color, one); code = gdev_vector_update_fill_color((gx_device_vector *) pdev, &color); /* ここを通過したら以下の色設定は無意味? */ } if (code < 0) return 0; esmv_write_begin(dev, depth, (int)x, (int)y, w, h, w, h, 0); { int i, j; uint width_bytes = (w + 7) >> 3; uint num_bytes = width_bytes * h; byte *buf = gs_alloc_bytes(vdev->memory, num_bytes, "esmv_copy_mono(buf)"); if (data_x % 8 == 0) { for (i = 0; i < h; ++i) { memcpy(buf + i * width_bytes, data + (data_x >> 3) + i * raster, width_bytes); } } else { for (i = 0; i < h; ++i) { for (j = 0; j < width_bytes; j++) { *(buf + i * width_bytes + j) = *(data + (data_x >> 3) + i * raster + j) << (data_x % 8) | *(data + (data_x >> 3) + i * raster + j + 1) >> (8 - data_x % 8); } } } esmv_write_data(dev, depth, buf, num_bytes, w, h); gs_free_object(vdev->memory, buf, "esmv_copy_mono(buf)"); } esmv_write_end(dev, depth); return 0; } /* Copy a color bitmap. */ private int esmv_copy_color(gx_device * dev, const byte * data, int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h) { gx_device_esmv *const pdev = (gx_device_esmv *) dev; gx_device_vector *const vdev = (gx_device_vector *) dev; int depth = dev->color_info.depth; int num_components = (depth < 24 ? 1 : 3); uint width_bytes = w * num_components; if (pdev->MaskState != 0) { /* lputs(s, ESC_GS "1owE");*/ pdev->MaskState = 0; } esmv_write_begin(dev, depth, (int)x, (int)y, w, h, w, h, 0); { int i; uint num_bytes = width_bytes * h; byte *buf = gs_alloc_bytes(vdev->memory, num_bytes, "esmv_copy_color(buf)"); for (i = 0; i < h; ++i) { memcpy(buf + i * width_bytes, data + ((data_x * depth) >> 3) + i * raster, width_bytes); } esmv_write_data(dev, depth, buf, num_bytes, w, h); gs_free_object(vdev->memory, buf, "esmv_copy_color(buf)"); } esmv_write_end(dev, depth); return 0; } /* Fill a mask. */ private int esmv_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) { gx_device_vector const *vdev = (gx_device_vector *) dev; gx_device_esmv *pdev = (gx_device_esmv *) dev; stream *s = gdev_vector_stream(vdev); gx_color_index color = gx_dc_pure_color(pdcolor); char obuf[64]; if (w <= 0 || h <= 0) return 0; if (depth > 1 || gdev_vector_update_fill_color(vdev, pdcolor) < 0 || gdev_vector_update_clip_path(vdev, pcpath) < 0 || gdev_vector_update_log_op(vdev, lop) < 0 ) return gx_default_fill_mask(dev, data, data_x, raster, id, x, y, w, h, pdcolor, depth, lop, pcpath); #if 0 (*dev_proc(vdev->bbox_device, fill_mask)) ((gx_device *) vdev->bbox_device, data, data_x, raster, id, x, y, w, h, pdcolor, depth, lop, pcpath); #endif if (!gx_dc_is_pure(pdcolor)) return_error(gs_error_rangecheck); pdev->current_color = color; (void)sprintf(obuf, ESC_GS "0;0;100spE" ESC_GS "1;1;%dccE" ,color); lputs(s, obuf); if (vdev->x_pixels_per_inch == 1200) { lputs(s, ESC_GS "1;45;156htmE"); } else if (vdev->x_pixels_per_inch == 600) { lputs(s, ESC_GS "1;45;106htmE"); } else { lputs(s, ESC_GS "1;45;71htmE"); } if(pdev->MaskState != 1) { /* lputs(s, ESC_GS "1owE");*/ pdev->MaskState = 1; } esmv_write_begin(dev, depth, (int)x, (int)y, w, h, w, h, 0); { int i; uint width_bytes = (w + 7) >> 3; uint num_bytes = width_bytes * h; byte *buf = gs_alloc_bytes(vdev->memory, num_bytes, "esmv_fill_mask(buf)"); for (i = 0; i < h; ++i) { memcpy(buf + i * width_bytes, data + (data_x >> 3) + i * raster, width_bytes); } esmv_write_data(dev, depth, buf, num_bytes, w, h); esmv_write_end(dev, depth); gs_free_object(vdev->memory, buf, "esmv_fill_mask(buf)"); } return 0; } /* ---------------- High-level images ---------------- */ private image_enum_proc_plane_data(esmv_image_plane_data); private image_enum_proc_end_image(esmv_image_end_image); private const gx_image_enum_procs_t esmv_image_enum_procs = { esmv_image_plane_data, esmv_image_end_image }; /* Start processing an image. */ private int esmv_begin_image(gx_device * dev, const gs_imager_state * pis, const gs_image_t * pim, gs_image_format_t format, const gs_int_rect * prect, const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, gs_memory_t * mem, gx_image_enum_common_t **pinfo) { gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; stream *s = gdev_vector_stream((gx_device_vector *) pdev); gdev_vector_image_enum_t *pie = gs_alloc_struct(mem, gdev_vector_image_enum_t, &st_vector_image_enum, "esmv_begin_image"); const gs_color_space *pcs = pim->ColorSpace; gx_color_index color = gx_dc_pure_color(pdcolor); gs_color_space_index index; int num_components = 1; bool can_do = prect == 0 && (pim->format == gs_image_format_chunky || pim->format == gs_image_format_component_planar); gs_matrix imat; int code; int ty, bx, by, cx, cy, dx, dy, sx, sy; char obuf[128]; if (pie == 0) return_error(gs_error_VMerror); pie->memory = mem; code = gdev_vector_begin_image(vdev, pis, pim, format, prect, pdcolor, pcpath, mem, &esmv_image_enum_procs, pie); if (code < 0) return code; *pinfo = (gx_image_enum_common_t *) pie; if (!pim->ImageMask) { index = gs_color_space_get_index(pcs); num_components = gs_color_space_num_components(pcs); if (pim->CombineWithColor) { can_do = false; } else { switch (index) { case gs_color_space_index_DeviceGray: if ((pim->Decode[0] != 0 || pim->Decode[1] != 1) && (pim->Decode[0] != 1 || pim->Decode[1] != 0)) can_do = false; break; case gs_color_space_index_DeviceRGB: if (pim->Decode[0] != 0 || pim->Decode[1] != 1 || pim->Decode[2] != 0 || pim->Decode[3] != 1 || pim->Decode[4] != 0) can_do = false; break; default: can_do = false; } } } if (!can_do) { return gx_default_begin_image(dev, pis, pim, format, prect, pdcolor, pcpath, mem, &pie->default_info); } if (pim->ImageMask || (pim->BitsPerComponent == 1 && num_components == 1)) { if (pim->Decode[0] > pim->Decode[1]) { pdev->MaskReverse = 1; } else { pdev->MaskReverse = 0; } } /* Write the image/colorimage/imagemask preamble. */ gs_matrix_invert(&pim->ImageMatrix, &imat); gs_matrix_multiply(&imat, &ctm_only(pis), &imat); ty = imat.ty; bx = imat.xx * pim->Width + imat.yx * pim->Height + imat.tx; by = imat.xy * pim->Width + imat.yy * pim->Height + imat.ty; cx = imat.yx * pim->Height + imat.tx; cy = imat.yy * pim->Height + imat.ty; dx = imat.xx * pim->Width + imat.tx; dy = imat.xy * pim->Width + imat.ty; sx = bx - (int)imat.tx; sy = by - (int)imat.ty; /* とりあえず絵の位置に収まるように強制的に座標を変更する。 */ pdev -> roll = 0; pdev -> reverse_x = pdev -> reverse_y = 0; if (imat.tx > bx) { pdev -> reverse_x = 1; sx = -sx; imat.tx = bx; } if (imat.ty > by) { pdev -> reverse_y = 1; sy = -sy; imat.ty = by; } (void)memcpy(&pdev -> xmat, &imat, sizeof(gs_matrix)); pdev -> sx = sx; pdev -> sy = sy; pdev -> h = pim->Height; pdev -> w = pim->Width; pdev -> dd = 0; pdev -> bx = 0; pdev -> by = 0; if (ty == cy) { /* 回転時の描画については現在未実装。GS 側の機能を使用する */ return -1; } if (pim->ImageMask) { pdev->ncomp = 1; /* 描画論理設定命令 - 透過 */ if (pdev->MaskState != 1) { /* lputs(s, ESC_GS "1owE");*/ (void)sprintf(obuf, ESC_GS "1;1;%dccE", color); lputs(s, obuf); if (vdev->x_pixels_per_inch == 1200) { lputs(s, ESC_GS "1;45;156htmE"); } else if (vdev->x_pixels_per_inch == 600) { lputs(s, ESC_GS "1;45;106htmE"); } else { lputs(s, ESC_GS "1;45;71htmE"); } } } else { /* 描画論理設定命令 - 白塗り */ if (pdev->MaskState != 0) { /* lputs(s, ESC_GS "1owE");*/ /* 184->204 */ pdev->MaskState = 0; } pdev->ncomp = num_components; } if (pdev -> reverse_y) return 0; esmv_write_begin(dev, pie->bits_per_pixel, (int)imat.tx, (int)imat.ty, pie->width, pie->height, sx, sy, pdev -> roll); return 0; } /* Process the next piece of an image. */ private int #if GS_VERSION_MAJOR >= 6 esmv_image_plane_data(gx_image_enum_common_t *info, const gx_image_plane_t *planes, int height, int *rows_used) #else esmv_image_plane_data(gx_device *dev, gx_image_enum_common_t *info, const gx_image_plane_t *planes, int height) #endif { #if GS_VERSION_MAJOR >= 6 gx_device *dev = info->dev; #endif gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info; int y; int plane; int width_bytes, tbyte; byte *buf; if (pie->default_info) return gx_image_plane_data(pie->default_info, planes, height); gx_image_plane_data(pie->bbox_info, planes, height); { #if GS_VERSION_MAJOR >= 6 if (height == 260) height = 1; #endif width_bytes = (pie->width * pie->bits_per_pixel / pdev->ncomp + 7) / 8 * pdev->ncomp; tbyte = width_bytes * height; buf = gs_alloc_bytes(vdev->memory, tbyte, "esmv_image_data(buf)"); if (pdev -> reverse_y) { if (pdev -> h == height) { #if 1 if(tbyte == 1){ if(strcmp(pdev->dname, "lp1800") != 0 && strcmp(pdev->dname, "lp9600") != 0) { pdev->w += pdev->sx / 2048; height += pdev->sy / 2048; } } #endif esmv_write_begin(dev, pie->bits_per_pixel, (int)pdev -> xmat.tx, (int)pdev -> xmat.ty, pdev -> w, height, (int)pdev -> sx, (int)pdev -> sy, pdev -> roll); } else { float yy, sy; yy = (pdev -> h * pdev->xmat.yy) - (pdev -> dd * pdev -> xmat.yy) - (height * pdev -> xmat.yy); if (yy == 0) { yy = (pdev -> h * pdev->xmat.yx) - (pdev -> dd * pdev -> xmat.yx) - (height * pdev -> xmat.yx); } if (pdev -> by) { sy = (int)pdev -> xmat.ty - (int)yy; sy = pdev -> by - (int)sy; } else { sy = height * pdev -> xmat.yy + 0.5; } if (sy < 0) { sy = -sy; } esmv_write_begin(dev, pie->bits_per_pixel, (int)pdev -> xmat.tx, (int)pdev -> xmat.ty - (int)yy, pdev -> w, height, (int)pdev -> sx, (int)sy, pdev -> roll); pdev -> by = (int)pdev -> xmat.ty - (int)yy; } } pdev -> dd += height; for (plane = 0; plane < pie->num_planes; ++plane) { for (y = 0; y < height; ++y) { int bit, w; char *p, *d, c; p = planes[plane].data + ((planes[plane].data_x * pie->bits_per_pixel) >> 3) + y * planes[plane].raster; if (pdev -> reverse_y) { d = buf + (height - y) * width_bytes; if (!pdev -> reverse_x) { (void)memcpy(buf + (height - y - 1) * width_bytes, planes[plane].data + ((planes[plane].data_x * pie->bits_per_pixel) >> 3) + y * planes[plane].raster, width_bytes); } } else { d = buf + (y + 1) * width_bytes; if (!pdev -> reverse_x) { (void)memcpy(buf + y * width_bytes, planes[plane].data + ((planes[plane].data_x * pie->bits_per_pixel) >> 3) + y * planes[plane].raster, width_bytes); } } if (pdev -> reverse_x) { if (pie->bits_per_pixel == 1) { for (w = 0; w < width_bytes; w++) { c = 0; for (bit = 0; bit < 8; bit++) { if (*p & 1 << (7 - bit)) { c |= 1 << bit; } } p++; *--d = c; } } else if (pie->bits_per_pixel == 8){ for (w = 0; w < width_bytes; w++) { *--d = *p++; } } else { for (w = 0; w < width_bytes / 3; w++) { *--d = *(p + 2); *--d = *(p + 1); *--d = *p; p += 3; } } } } } #if 1 if(tbyte == 1){ int t; gs_free_object(vdev->memory, buf, "esmv_image_data(buf)"); if(strcmp(pdev->dname, "lp1800") == 0 || strcmp(pdev->dname, "lp9600") == 0) { if(pdev->sx > pdev->sy){ height = pdev->sy; pdev->w = pdev->sx; tbyte = ((pdev->sx + 7) / 8) * pdev->sy; } else { if(pdev->sx < pdev->sy){ height = pdev->sy; pdev->w = pdev->sx; tbyte = ((pdev->sx + 7) / 8) * pdev->sy; } else { tbyte = 1; } } } else { if(pdev->sx > pdev->sy){ tbyte = 1; } else { if(pdev->sx < pdev->sy){ tbyte = tbyte * height; } else { tbyte = 1; } } } buf = gs_alloc_bytes(vdev->memory, tbyte, "esmv_image_data(buf)"); for(t = 0; t < tbyte; t++){ buf[t] = 0xff; } } #endif esmv_write_data(dev, pie->bits_per_pixel, buf, tbyte, pdev -> w, height); if (pdev -> reverse_y) { esmv_write_end(dev, pie->bits_per_pixel); } gs_free_object(vdev->memory, buf, "esmv_image_data(buf)"); } return (pie->y += height) >= pie->height; } private int #if GS_VERSION_MAJOR >= 6 esmv_image_end_image(gx_image_enum_common_t * info, bool draw_last) #else esmv_image_end_image(gx_device * dev, gx_image_enum_common_t * info, bool draw_last) #endif { #if GS_VERSION_MAJOR >= 6 gx_device *dev = info->dev; #endif gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info; int code; if (!(pdev -> reverse_y)) { esmv_write_end(dev, pie->bits_per_pixel); } pdev->reverse_x = pdev->reverse_y = 0; if (pdev->MaskReverse == 0) { ; } pdev->MaskReverse = -1; code = gdev_vector_end_image(vdev, (gdev_vector_image_enum_t *) pie, draw_last, pdev->white); return code; } private void esmv_write_begin(gx_device *dev, int bits, int x, int y, int sw, int sh, int dw, int dh, int roll) { gx_device_esmv *const pdev = (gx_device_esmv *)dev; stream *s = gdev_vector_stream((gx_device_vector *)pdev); char obuf[128]; int comp; (void)sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y); lputs(s, obuf); comp = 10; if (bits == 1) { if (strcmp(pdev->dname, "lp1800") == 0 || strcmp(pdev->dname, "lp9600") == 0) { (void)sprintf(obuf, ESC_GS "0bcI"); }else{ (void)sprintf(obuf, ESC_GS "5;%d;%d;%d;%d;%dsrI", sw, sh, dw, dh, roll); } } else if (bits == 4) { if (pdev -> c4map) { pdev -> c4map = FALSE; } (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll); } else if (bits == 8) { if (pdev -> c8map) { pdev -> c8map = FALSE; } (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll); } else { /* 24 bit */ (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll); } lputs(s, obuf); return; } private void esmv_write_data(gx_device *dev, int bits, char *buf, int bsize, int w, int ras) { gx_device_vector *const vdev = (gx_device_vector *) dev; gx_device_esmv *const pdev = (gx_device_esmv *) dev; stream *s = gdev_vector_stream((gx_device_vector *)pdev); char obuf[128]; int size; char *tmps, *p; if (bits == 12) { p = tmps = gs_alloc_bytes(vdev->memory, bsize * 2, "esmv_write_data(tmp)"); for (size = 0; size < bsize; size++) { *p++ = buf[size] & 0xF0; *p++ = buf[size] << 4; } bsize = bsize * 2; buf = tmps; } if(bits == 4) { p = tmps = gs_alloc_bytes(vdev->memory, bsize * 2, "esmv_write_data(tmp)"); for (size = 0; size < bsize; size++) { *p++ = ((buf[size] & 0xF0) * 0xFF / 0xF0); *p++ = ((buf[size] << 4 & 0xF0) * 0xFF / 0xF0); } bsize = bsize * 2; buf = tmps; } if(bits == 1){ if (strcmp(pdev->dname, "lp1800") == 0 || \ strcmp(pdev->dname, "lp9600") == 0) { (void)sprintf(obuf, ESC_GS "%d;1;%d;%d;0db{I", bsize, w, ras); }else{ (void)sprintf(obuf, ESC_GS "%d;%du{I", bsize, ras); } }else{ (void)sprintf(obuf, ESC_GS "%d;%dcu{I", bsize, ras); } lputs(s, obuf); put_bytes(s, buf, bsize); if (bits == 12 || bits == 4) { gs_free_object(vdev->memory, tmps, "esmv_write_data(tmp)"); } return; } private void esmv_write_end(gx_device *dev, int bits) { gx_device_esmv *const pdev = (gx_device_esmv *) dev; stream *s = gdev_vector_stream((gx_device_vector *)pdev); if(bits == 1){ if (strcmp(pdev->dname, "lp1800") == 0 || \ strcmp(pdev->dname, "lp9600") == 0) { lputs(s, ESC_GS "1dbI"); } else { lputs(s, ESC_GS "erI"); } }else{ lputs(s, ESC_GS "ecrI"); } return; }