/* IW; */ int hpgl_IW(hpgl_args_t *pargs, hpgl_state_t *pgls) { hpgl_real_t wxy[4]; int i; gs_int_rect win; hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); /* get the default picture frame coordinates. */ hpgl_call(hpgl_picture_frame_coords(pgls, &win)); wxy[0] = win.p.x; wxy[1] = win.p.y; wxy[2] = win.q.x; wxy[3] = win.q.y; for ( i = 0; i < 4 && hpgl_arg_units(pgls->memory, pargs, &wxy[i]); ++i ) ; if ( i & 3 ) return e_Range; /* no args case disables the soft clip window */ if ( i == 0 ) { pgls->g.soft_clip_window.active = false; pgls->g.soft_clip_window.isbound = false; return 0; } /* HAS needs error checking */ pgls->g.soft_clip_window.rect.p.x = wxy[0]; pgls->g.soft_clip_window.rect.p.y = wxy[1]; pgls->g.soft_clip_window.rect.q.x = wxy[2]; pgls->g.soft_clip_window.rect.q.y = wxy[3]; pgls->g.soft_clip_window.active = true; return 0; }
static int hpgl_picture_frame_coords(hpgl_state_t *pgls, gs_int_rect *gl2_win) { gs_rect dev_win; /* device window */ hpgl_real_t x1 = pgls->g.picture_frame.anchor_point.x; hpgl_real_t y1 = pgls->g.picture_frame.anchor_point.y; hpgl_real_t x2 = x1 + pgls->g.picture_frame_width; hpgl_real_t y2 = y1 + pgls->g.picture_frame_height; pcl_set_ctm(pgls, false); hpgl_call(gs_transform(pgls->pgs, x1, y1, &dev_win.p)); hpgl_call(gs_transform(pgls->pgs, x2, y2, &dev_win.q)); hpgl_call(hpgl_set_plu_ctm(pgls)); /* * gs_bbox_transform_inverse puts the resulting points in the * correct order, with p < q. */ { gs_matrix mat; gs_rect pcl_win; /* pcl window */ gs_currentmatrix(pgls->pgs, &mat); hpgl_call(gs_bbox_transform_inverse(&dev_win, &mat, &pcl_win)); /* Round all coordinates to the nearest integer. */ #define set_round(e) gl2_win->e = (int)floor(pcl_win.e + 0.5) set_round(p.x); set_round(p.y); set_round(q.x); set_round(q.y); #undef set_round } /* restore the ctm */ hpgl_call(hpgl_set_ctm(pgls)); return 0; }
/* PG; */ int hpgl_PG(hpgl_args_t *pargs, hpgl_state_t *pgls) { if ( pgls->personality == rtl ) { int dummy; hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); /* with parameter always feed, without parameter feed if marked */ if ( pcl_page_marked(pgls) || hpgl_arg_c_int(pgls->memory, pargs, &dummy) ) hpgl_call(pcl_do_FF(pgls)); } return 0; }
/* RO; */ int hpgl_RO(hpgl_args_t *pargs, hpgl_state_t *pgls) { int angle=0; gs_point point, dev_pt; /* this business is used by both SC and RO -- perhaps it needs a new home */ hpgl_call(hpgl_set_ctm(pgls)); hpgl_call(hpgl_get_current_position(pgls, &point)); hpgl_call(gs_transform(pgls->pgs, point.x, point.y, &dev_pt)); if ( hpgl_arg_c_int(pgls->memory, pargs, &angle) ) switch ( angle ) { case 0: case 90: case 180: case 270: break; default: return e_Range; } if ( angle != pgls->g.rotation ) { hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); pgls->g.rotation = angle; hpgl_call(hpgl_set_ctm(pgls)); hpgl_call(gs_itransform(pgls->pgs, dev_pt.x, dev_pt.y, &point)); hpgl_call(hpgl_set_current_position(pgls, &point)); hpgl_call(hpgl_update_carriage_return_pos(pgls)); } return 0; }
/* IR; */ int hpgl_IR(hpgl_args_t *pargs, hpgl_state_t *pgls) { hpgl_real_t rptxy[4]; int i; hpgl_args_t args; gs_int_rect win; for ( i = 0; i < 4 && hpgl_arg_c_real(pgls->memory, pargs, &rptxy[i]); ++i ) ; if ( i & 1 ) return e_Range; /* get the PCL picture frame coordinates */ hpgl_call(hpgl_picture_frame_coords(pgls, &win)); hpgl_args_setup(&args); if ( i != 0 ) { hpgl_args_add_int(&args, win.p.x + (win.q.x - win.p.x) * rptxy[0] / 100.0); hpgl_args_add_int(&args, win.p.y + (win.q.y - win.p.y) * rptxy[1] / 100.0); } if ( i == 4 ) { hpgl_args_add_int(&args, win.p.x + (win.q.x - win.p.x) * rptxy[2] / 100.0); hpgl_args_add_int(&args, win.p.y + (win.q.y - win.p.y) * rptxy[3] / 100.0); } hpgl_IP( &args, pgls ); return 0; }
/* IP; */ int hpgl_IP(hpgl_args_t *pargs, hpgl_state_t *pgls) { int32 ptxy[4]; int i; gs_int_rect win; /* draw the current path */ hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); /* get the default picture frame coordinates */ hpgl_call(hpgl_picture_frame_coords(pgls, &win)); /* round the picture frame coordinates */ ptxy[0] = win.p.x; ptxy[1] = win.p.y; ptxy[2] = win.q.x; ptxy[3] = win.q.y; for ( i = 0; i < 4 && hpgl_arg_int(pgls->memory, pargs, &ptxy[i]); ++i ) ; if ( i & 1 ) return e_Range; if ( i == 2 ) { pgls->g.P2.x = (ptxy[0] - pgls->g.P1.x) + pgls->g.P2.x; pgls->g.P2.y = (ptxy[1] - pgls->g.P1.y) + pgls->g.P2.y; pgls->g.P1.x = ptxy[0]; pgls->g.P1.y = ptxy[1]; } else { pgls->g.P1.x = ptxy[0]; pgls->g.P1.y = ptxy[1]; pgls->g.P2.x = ptxy[2]; pgls->g.P2.y = ptxy[3]; } /* if either coordinate is equal it is incremented by 1 */ if ( pgls->g.P1.x == pgls->g.P2.x ) pgls->g.P2.x++; if ( pgls->g.P1.y == pgls->g.P2.y ) pgls->g.P2.y++; return 0; }
/* LO [origin]; */ int hpgl_LO(hpgl_args_t * pargs, hpgl_state_t * pgls) { int origin = 1; hpgl_arg_c_int(pgls->memory, pargs, &origin); if (origin < 1 || origin == 10 || origin == 20 || origin > 21) return e_Range; pgls->g.label.origin = origin; hpgl_call(hpgl_update_carriage_return_pos(pgls)); return 0; }
/* DV [path[,line]]; */ int hpgl_DV(hpgl_args_t * pargs, hpgl_state_t * pgls) { int path = 0, line = 0; hpgl_arg_c_int(pgls->memory, pargs, &path); hpgl_arg_c_int(pgls->memory, pargs, &line); if ((path & ~3) | (line & ~1)) return e_Range; pgls->g.character.text_path = path; pgls->g.character.line_feed_direction = (line ? -1 : 1); hpgl_call(hpgl_update_carriage_return_pos(pgls)); return 0; }
/* * NP [n]; */ int hpgl_NP(hpgl_args_t * pargs, hpgl_state_t * pgls) { int32 n = 8; if (pgls->personality == pcl5e) return 0; /* output any current path */ hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); if (hpgl_arg_int(pgls->memory, pargs, &n) && ((n < 2) || (n > 32768))) return e_Range; return pcl_palette_NP(pgls, n); }
/* * PC [pen[,primary1,primary2,primary3]; */ static int hpgl_PC(hpgl_args_t * pargs, hpgl_state_t * pgls) { int32 pen; int32 npen = pcl_palette_get_num_entries(pgls->ppalet); if (pgls->personality == pcl5e) return 0; /* output any current path */ hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); if (hpgl_arg_int(pgls->memory, pargs, &pen)) { hpgl_real_t primary[3]; if ((pen < 0) || (pen >= npen)) return e_Range; if (hpgl_arg_c_real(pgls->memory, pargs, &primary[0])) { float comps[3]; if (!hpgl_arg_c_real(pgls->memory, pargs, &primary[1]) || !hpgl_arg_c_real(pgls->memory, pargs, &primary[2])) return e_Range; comps[0] = primary[0]; comps[1] = primary[1]; comps[2] = primary[2]; return pcl_palette_set_color(pgls, pen, comps); } else return pcl_palette_set_default_color(pgls, pen); } else { int i; int code; for (i = 0; i < npen; ++i) { if ((code = pcl_palette_set_default_color(pgls, i)) < 0) return code; } } return 0; }
/* * The "implicit" portion of the IN command. * * With the advent of PCL 5c, both PCL and GL want to reset the current * palette. The difficulty is that they want to reset it to different things. * * The proper way to handle this would be to implement IN as a reset type, * create a single palette reset routine, and have it do different things * depending on the nature of the reset. * * At the time this comment was written, such a change was larger than could * be easily accommodated. Hence, a less drastic alternative was employed: * split the IN command into implicit and explicit portions, and only use the * latter when the IN command is explicitly invoked. */ int hpgl_IN_implicit( hpgl_state_t * pgls\ ) { hpgl_args_t args; /* cancel rotation */ pgls->g.rotation = 0; /* restore defaults */ hpgl_DF(&args, pgls); /* if in RTL mode provided initial values for PS */ if ( pgls->personality == rtl ) { hpgl_args_setup(&args); hpgl_PS(&args, pgls); } /* defaults P1 and P2 */ hpgl_args_setup(&args); hpgl_IP(&args, pgls); /* pen width units - metric, also resets pen widths. */ hpgl_args_setup(&args); hpgl_WU(&args, pgls); /* * pen up-absolute position and set gl/2 current positon to * 0,0 or the lower left of the picture frame. Simply sets * the gl/2 state, we subsequently clear the path because we * do not want to create a live gs path. */ hpgl_args_set_real2(&args, 0.0, 0.0); hpgl_PU(&args, pgls); hpgl_args_set_real2(&args, 0.0, 0.0); hpgl_PA(&args, pgls); hpgl_call(hpgl_clear_current_path(pgls)); return 0; }
/* Define label drawing direction (DI, DR). */ static int hpgl_label_direction(hpgl_args_t * pargs, hpgl_state_t * pgls, bool relative) { hpgl_real_t run = 1, rise = 0; if (hpgl_arg_c_real(pgls->memory, pargs, &run)) { if (!hpgl_arg_c_real(pgls->memory, pargs, &rise) || (run == 0 && rise == 0)) return e_Range; { double hyp = hypot(run, rise); run /= hyp; rise /= hyp; } } pgls->g.character.direction.x = run; pgls->g.character.direction.y = rise; pgls->g.character.direction_relative = relative; hpgl_call(hpgl_update_carriage_return_pos(pgls)); return 0; }
/* DF; sets programmable features except P1 and P2 */ int hpgl_DF(hpgl_args_t *pargs, hpgl_state_t *pgls) { hpgl_args_t args; hpgl_call(hpgl_reset_overlay(pgls)); hpgl_args_setup(&args); hpgl_FT(&args, pgls); hpgl_args_setup(&args); hpgl_IW(&args, pgls); hpgl_set_line_attribute_defaults(pgls); hpgl_args_setup(&args); hpgl_LA(&args, pgls); hpgl_set_line_pattern_defaults(pgls); hpgl_args_setup(&args); hpgl_RF(&args, pgls); hpgl_args_set_int(&args, 0); hpgl_SV(&args, pgls); hpgl_args_setup(&args); hpgl_UL(&args, pgls); hpgl_args_setup(&args); hpgl_SB(&args, pgls); return 0; }
/* SC; */ int hpgl_SC(hpgl_args_t *pargs, hpgl_state_t *pgls) { hpgl_real_t xy[4]; int i; int type; hpgl_scaling_params_t scale_params; gs_point point, dev_pt, dev_anchor; scale_params = pgls->g.scaling_params; hpgl_call(hpgl_get_current_position(pgls, &point)); hpgl_call(gs_transform(pgls->pgs, point.x, point.y, &dev_pt)); hpgl_call(gs_transform(pgls->pgs, pgls->g.anchor_corner.x, pgls->g.anchor_corner.y, &dev_anchor)); for ( i = 0; i < 4 && hpgl_arg_real(pgls->memory, pargs, &xy[i]); ++i ) ; switch ( i ) { case 0: /* set defaults */ { /* a naked SC implies the soft clip window is bound to plotter units. */ gs_matrix umat; type = hpgl_scaling_none; hpgl_compute_user_units_to_plu_ctm(pgls, &umat); /* in-place */ hpgl_call(gs_bbox_transform(&pgls->g.soft_clip_window.rect, &umat, &pgls->g.soft_clip_window.rect)); pgls->g.soft_clip_window.isbound = true; break; } default: return e_Range; case 4: type = hpgl_scaling_anisotropic; hpgl_arg_c_int(pgls->memory, pargs, &type); switch ( type ) { case hpgl_scaling_anisotropic: /* 0 */ if ( xy[0] == xy[1] || xy[2] == xy[3] ) return e_Range; pxy: scale_params.pmin.x = xy[0]; scale_params.pmax.x = xy[1]; scale_params.pmin.y = xy[2]; scale_params.pmax.y = xy[3]; break; case hpgl_scaling_isotropic: /* 1 */ if ( xy[0] == xy[1] || xy[2] == xy[3] ) return e_Range; { hpgl_real_t left = 50, bottom = 50; if ( (hpgl_arg_c_real(pgls->memory, pargs, &left) && (left < 0 || left > 100 || !hpgl_arg_c_real(pgls->memory, pargs, &bottom) || bottom < 0 || bottom > 100)) ) return e_Range; scale_params.left = left; scale_params.bottom = bottom; } goto pxy; case hpgl_scaling_point_factor: /* 2 */ if ( xy[1] == 0 || xy[3] == 0 ) return e_Range; scale_params.pmin.x = xy[0]; scale_params.factor.x = xy[1]; scale_params.pmin.y = xy[2]; scale_params.factor.y = xy[3]; break; default: return e_Range; } } hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); pgls->g.scaling_params = scale_params; pgls->g.scaling_type = type; hpgl_call(hpgl_set_ctm(pgls)); hpgl_call(gs_itransform(pgls->pgs, dev_pt.x, dev_pt.y, &point)); hpgl_call(hpgl_set_current_position(pgls, &point)); hpgl_call(gs_itransform(pgls->pgs, dev_anchor.x, dev_anchor.y, &pgls->g.anchor_corner)); /* PCLTRM 23-7 (commands the update cr position) does not list SC but PCL updates the position */ hpgl_call(hpgl_update_carriage_return_pos(pgls)); return 0; }
/* The part of the DF command applicable for overlay macros */ int hpgl_reset_overlay(hpgl_state_t *pgls) { hpgl_args_t args; hpgl_args_setup(&args); hpgl_AC(&args, pgls); hpgl_args_setup(&args); pgls->g.font_selected = 0; hpgl_AD(&args, pgls); hpgl_args_setup(&args); hpgl_SD(&args, pgls); hpgl_args_setup(&args); hpgl_CF(&args, pgls); hpgl_args_setup(&args); hpgl_args_add_int(&args, 1); hpgl_args_add_int(&args, 0); hpgl_DI(&args, pgls); /* HAS -- Figure out some way to do this so that it is consistant */ pgls->g.label.terminator = 3; pgls->g.label.print_terminator = false; hpgl_args_setup(&args); hpgl_DV(&args, pgls); hpgl_args_setup(&args); hpgl_ES(&args, pgls); pgls->g.label.write_vertical = false; pgls->g.label.double_byte = false; hpgl_args_setup(&args); hpgl_LM(&args, pgls); hpgl_args_set_int(&args, 1); hpgl_LO(&args, pgls); /* we do this instead of calling SC directly */ if ( pgls->g.scaling_type != hpgl_scaling_none ) { gs_point dpt, pt; /* device point and user point */ hpgl_call(hpgl_get_current_position(pgls, &pt)); hpgl_call(gs_transform(pgls->pgs, pt.x, pt.y, &dpt)); pgls->g.scaling_type = hpgl_scaling_none; hpgl_call(hpgl_set_ctm(pgls)); hpgl_call(gs_itransform(pgls->pgs, dpt.x, dpt.y, &pt)); hpgl_call(hpgl_set_current_position(pgls, &pt)); } pgls->g.fill_type = hpgl_even_odd_rule; hpgl_args_set_int(&args,0); hpgl_PM(&args, pgls); hpgl_args_set_int(&args,2); hpgl_PM(&args, pgls); pgls->g.bitmap_fonts_allowed = 0; hpgl_args_setup(&args); hpgl_SI(&args, pgls); hpgl_args_setup(&args); hpgl_SL(&args, pgls); /* We initialize symbol mode directly because hpgl_SM parses its argument differently than most other commands */ pgls->g.symbol_mode = 0; hpgl_args_setup(&args); hpgl_SS(&args, pgls); hpgl_args_set_int(&args,1); hpgl_TR(&args, pgls); hpgl_args_setup(&args); hpgl_TD(&args, pgls); hpgl_args_setup(&args); hpgl_MC(&args, pgls); #ifdef LJ6_COMPAT /* LJ6 seems to reset PP with an IN command the Color Laserjet does not. NB this needs to be handled with dynamic configuration */ hpgl_args_setup(&args); hpgl_PP(&args, pgls); #endif return 0; }