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; }
/* 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; }
/* * End (raster) graphics mode. This may be called explicitly by either of the * end graphics mode commands (<esc>*rB or <esc>*rC), or implicitly by any * commmand which is neither legal nor ignored in graphics mode. */ int pcl_end_graphics_mode( pcl_state_t * pcs ) { gs_point cur_pt; gs_matrix dev2pd; /* close the raster; exit graphics mode */ pcl_complete_raster(pcs); pcs->raster_state.graphics_mode = false; /* get the new current point; then restore the graphic state */ gs_transform(pcs->pgs, 0.0, 0.0, &cur_pt); pcl_grestore(pcs); /* transform the new point back to "pseudo print direction" space */ pcl_invert_mtx(&(pcs->xfm_state.pd2dev_mtx), &dev2pd); gs_point_transform(cur_pt.x, cur_pt.y, &dev2pd, &cur_pt); pcl_set_cap_x(pcs, (coord)(cur_pt.x + 0.5) - adjust_pres_mode(pcs), false, false); return pcl_set_cap_y( pcs, (coord)(cur_pt.y + 0.5) - pcs->margins.top, false, false, false, false ); }
/* Set up a clipping path and device for insideness testing. */ static int in_path(os_ptr oppath, i_ctx_t *i_ctx_p, gx_device * phdev) { int code = gs_gsave(igs); int npop; double uxy[2]; if (code < 0) return code; code = num_params(oppath, 2, uxy); if (code >= 0) { /* Aperture is a single pixel. */ gs_point dxy; gs_fixed_rect fr; gs_transform(igs, uxy[0], uxy[1], &dxy); fr.p.x = fixed_floor(float2fixed(dxy.x)); fr.p.y = fixed_floor(float2fixed(dxy.y)); fr.q.x = fr.p.x + fixed_1; fr.q.y = fr.p.y + fixed_1; code = gx_clip_to_rectangle(igs, &fr); npop = 2; } else if (code == e_stackunderflow) { /* If 0 elements, definitely a stackunderflow; otherwise, */ /* only 1 number, also a stackunderflow. */ npop = code; } else { /* Aperture is a user path. */ /* We have to set the clipping path without disturbing */ /* the current path. */ gx_path *ipath = igs->path; gx_path save; gx_path_init_local(&save, imemory); gx_path_assign_preserve(&save, ipath); gs_newpath(igs); code = upath_append(oppath, i_ctx_p, false); if (code >= 0) code = gx_clip_to_path(igs); gx_path_assign_free(igs->path, &save); npop = 1; } if (code < 0) { gs_grestore(igs); return code; } /* Install the hit detection device. */ gx_set_device_color_1(igs); gx_device_init((gx_device *) phdev, (const gx_device *)&gs_hit_device, NULL, true); phdev->width = phdev->height = max_int; gx_device_fill_in_procs(phdev); gx_set_device_only(igs, phdev); return npop; }
/* * Set up the pattern orientatin and reference point for GL. The anchor point * is taken as being in the current GL space, and the current transform is * assumed properly set. The orientation is that of the logical page. */ void pcl_xfm_gl_set_pat_ref_pt( pcl_state_t * pcs ) { gs_transform( pcs->pgs, pcs->g.anchor_corner.x, pcs->g.anchor_corner.y, &(pcs->pat_ref_pt) ); pcs->pat_ref_pt.x = floor(pcs->pat_ref_pt.x + 0.5); pcs->pat_ref_pt.y = floor(pcs->pat_ref_pt.y + 0.5); pcs->pat_orient = (pcs->xfm_state.lp_orient + (pcs->g.rotation / 90)) & 0x3; }
/* set variables other than setting the page device that do not default to pcl reset values */ void pxPassthrough_pcl_state_nonpage_exceptions(px_state_t * pxs) { /* xl cursor -> pcl cursor position */ gs_point xlcp, pclcp, dp; /* make the pcl ctm active, after resets the hpgl/2 ctm is active. */ pcl_set_graphics_state(global_pcs); /* xl current point -> device point -> pcl current point. If anything fails we assume the current point is not valid and use the cap from the pcl state initialization - pcl's origin */ if (gs_currentpoint(pxs->pgs, &xlcp) || gs_transform(pxs->pgs, xlcp.x, xlcp.y, &dp) || gs_itransform(global_pcs->pgs, dp.x, dp.y, &pclcp)) { global_pcs->cap.x = 0; global_pcs->cap.y = inch2coord(2.0 / 6.0); /* 1/6" off by 2x in resolution. */ if (gs_debug_c('i')) dmprintf2(pxs->memory, "passthrough: changing cap NO currentpoint (%d, %d) \n", global_pcs->cap.x, global_pcs->cap.y); } else { if (gs_debug_c('i')) dmprintf8(pxs->memory, "passthrough: changing cap from (%d,%d) (%d,%d) (%d, %d) (%d, %d) \n", global_pcs->cap.x, global_pcs->cap.y, (coord) xlcp.x, (coord) xlcp.y, (coord) dp.x, (coord) dp.y, (coord) pclcp.x, (coord) pclcp.y); global_pcs->cap.x = (coord) pclcp.x; global_pcs->cap.y = (coord) pclcp.y; } if (global_pcs->underline_enabled) global_pcs->underline_start = global_pcs->cap; global_char_angle = pxs->pxgs->char_angle; global_char_shear.x = pxs->pxgs->char_shear.x; global_char_shear.y = pxs->pxgs->char_shear.y; global_char_scale.x = pxs->pxgs->char_scale.x; global_char_scale.y = pxs->pxgs->char_scale.y; global_char_bold_value = pxs->pxgs->char_bold_value; }
void pcl_mark_page_for_current_pos(pcl_state_t *pcs) { /* nothing to do */ if ( pcs->page_marked ) return; /* convert current point to device space and check if it is inside device rectangle for the page */ { gs_fixed_rect page_bbox_fixed = pcs->xfm_state.dev_print_rect; gs_rect page_bbox_float; gs_point current_pt, dev_pt; page_bbox_float.p.x = fixed2float(page_bbox_fixed.p.x); page_bbox_float.p.y = fixed2float(page_bbox_fixed.p.y); page_bbox_float.q.x = fixed2float(page_bbox_fixed.q.x); page_bbox_float.q.y = fixed2float(page_bbox_fixed.q.y); if ( gs_currentpoint(pcs->pgs, ¤t_pt) < 0 ) { dprintf("Not expected to fail\n" ); return; } if ( gs_transform(pcs->pgs, current_pt.x, current_pt.y, &dev_pt) ) { dprintf("Not expected to fail\n" ); return; } /* half-open lower - not sure this is correct */ if ( dev_pt.x >= page_bbox_float.p.x && dev_pt.y >= page_bbox_float.p.y && dev_pt.x < page_bbox_float.q.x && dev_pt.y < page_bbox_float.q.y ) pcs->page_marked = true; } }
/* * We export this so we can call it from HP-GL/2 configurations. * Note that it returns 1 iff it changed the PCL CAP. * * ESC % <enum> A */ int rtl_enter_pcl_mode( pcl_args_t * pargs, pcl_state_t * pcs ) { int b = int_arg(pargs) & 1; if ( pcs->parse_other == (int(*)(void *, pcl_state_t *, stream_cursor_read *))hpgl_process ) { /* * We were in HP-GL/2 mode. Destroy the gl/2 polygon path * and conditionally copy back the cursor position. */ if (b != 0) { /* the usual user -> device -> user dance. */ gs_point pt, dev_pt; hpgl_call_mem(pcs->memory, hpgl_set_ctm(pcs)); hpgl_call_mem(pcs->memory, hpgl_get_current_position(pcs, &pt)); hpgl_call_mem(pcs->memory, gs_transform(pcs->pgs, pt.x, pt.y, &dev_pt)); hpgl_call_mem(pcs->memory, pcl_set_ctm(pcs, true)); hpgl_call_mem(pcs->memory, gs_itransform(pcs->pgs, dev_pt.x, dev_pt.y, &pt)); /* HPGL/2 uses floats for coordinates */ #define round(x) (((x) < 0.0) ? (ceil ((x) - 0.5)) : (floor ((x) + 0.5))) pcs->cap.x = round(pt.x); pcs->cap.y = round(pt.y); #undef round } } else b = 0; pcs->parse_other = 0; return b; /* not 0, see comment above */ }
static int pl_fapi_set_cache(gs_text_enum_t * penum, const gs_font_base * pbfont, const gs_string * char_name, int cid, const double pwidth[2], const gs_rect * pbbox, const double Metrics2_sbw_default[4], bool * imagenow) { gs_state *pgs = (gs_state *) penum->pis; float w2[6]; int code = 0; gs_fapi_server *I = pbfont->FAPI; if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1) && pwidth[0] == 1.0) { gs_rect tmp_pbbox; gs_matrix save_ctm; const gs_matrix id_ctm = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; /* This is kind of messy, but the cache entry has already been calculated using the in-force matrix. The problem is that we have to call gs_setcachedevice with the in-force matrix, not the rotated one, so we have to recalculate the extents to be correct for the rotated glyph. */ /* save the ctm */ gs_currentmatrix(pgs, &save_ctm); gs_setmatrix(pgs, &id_ctm); /* magic numbers - we don't completelely understand the translation magic used by HP. This provides a good approximation */ gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15)); gs_rotate(pgs, 90); gs_transform(pgs, pbbox->p.x, pbbox->p.y, &tmp_pbbox.p); gs_transform(pgs, pbbox->q.x, pbbox->q.y, &tmp_pbbox.q); w2[0] = pwidth[0]; w2[1] = pwidth[1]; w2[2] = tmp_pbbox.p.x; w2[3] = tmp_pbbox.p.y; w2[4] = tmp_pbbox.q.x; w2[5] = tmp_pbbox.q.y; gs_setmatrix(pgs, &save_ctm); } else { w2[0] = pwidth[0]; w2[1] = pwidth[1]; w2[2] = pbbox->p.x; w2[3] = pbbox->p.y; w2[4] = pbbox->q.x; w2[5] = pbbox->q.y; } if (pbfont->PaintType) { double expand = max(1.415, gs_currentmiterlimit(pgs)) * gs_currentlinewidth(pgs) / 2; w2[2] -= expand; w2[3] -= expand; w2[4] += expand; w2[5] += expand; } if (I->ff.embolden != 0) { code = gs_setcharwidth((gs_show_enum *) penum, pgs, w2[0], w2[1]); } else { if ((code = gs_setcachedevice((gs_show_enum *) penum, pgs, w2)) < 0) { return (code); } } if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1) && pwidth[0] == 1.0) { *imagenow = false; return (gs_error_unknownerror); } *imagenow = true; return (code); }
/* 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; }