/* SI [width,height]; */ int hpgl_SI(hpgl_args_t * pargs, hpgl_state_t * pgls) { hpgl_real_t width_cm, height_cm; if (hpgl_arg_c_real(pgls->memory, pargs, &width_cm)) { if (!hpgl_arg_c_real(pgls->memory, pargs, &height_cm)) return e_Range; /* this isn't documented but HP seems to ignore the command (retains previous value) if either parameter is zero. NB probably should use epsilon have not tested. */ if (width_cm == 0.0 || height_cm == 0.0) return e_Range; pgls->g.character.size.x = mm_2_plu(width_cm * 10); pgls->g.character.size.y = mm_2_plu(height_cm * 10); pgls->g.character.size_mode = hpgl_size_absolute; } else pgls->g.character.size_mode = hpgl_size_not_set; return 0; }
/* SR [width,height]; */ int hpgl_SR(hpgl_args_t * pargs, hpgl_state_t * pgls) { hpgl_real_t width_pct, height_pct; if (hpgl_arg_c_real(pgls->memory, pargs, &width_pct)) { if (!hpgl_arg_c_real(pgls->memory, pargs, &height_pct)) return e_Range; /* this isn't documented but HP seems to ignore the command (retains previous value) if either parameter is zero. NB probably should use epsilon have not tested. */ if (width_pct == 0.0 || height_pct == 0.0) return e_Range; pgls->g.character.size.x = width_pct / 100; pgls->g.character.size.y = height_pct / 100; } else { pgls->g.character.size.x = 0.0075; pgls->g.character.size.y = 0.015; } pgls->g.character.size_mode = hpgl_size_relative; 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; }
/* SL [slant]; */ int hpgl_SL(hpgl_args_t * pargs, hpgl_state_t * pgls) { hpgl_real_t slant = 0; hpgl_arg_c_real(pgls->memory, pargs, &slant); /* clamp to 89.5 degrees of char slant, avoids math issues around * tan 90degrees == infinity. Visually close to HP, * performance decrease as slant approaches tan(90). */ pgls->g.character.slant = slant > MAX_SL_TANGENT ? MAX_SL_TANGENT : slant < -MAX_SL_TANGENT ? -MAX_SL_TANGENT : slant; return 0; }
/* * CR [black reference point red, white reference point red, ...]; */ int hpgl_CR(hpgl_args_t * pargs, hpgl_state_t * pgls) { double b_ref_r, b_ref_g, b_ref_b, w_ref_r, w_ref_g, w_ref_b; if (pgls->personality == pcl5e) return 0; if (hpgl_arg_c_real(pgls->memory, pargs, &b_ref_r)) if (!hpgl_arg_c_real(pgls->memory, pargs, &w_ref_r) || !hpgl_arg_c_real(pgls->memory, pargs, &b_ref_g) || !hpgl_arg_c_real(pgls->memory, pargs, &w_ref_g) || !hpgl_arg_c_real(pgls->memory, pargs, &b_ref_b) || !hpgl_arg_c_real(pgls->memory, pargs, &w_ref_b)) return e_Range; else return pcl_palette_CR(pgls, w_ref_r, w_ref_g, w_ref_b, b_ref_r, b_ref_g, b_ref_b); else /* no args - default references */ return pcl_palette_CR(pgls, 255, 255, 255, 0, 0, 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; }
/* Define font parameters (AD, SD). */ static int hpgl_font_definition(hpgl_args_t * pargs, hpgl_state_t * pgls, int index) { /* * Since these commands take an arbitrary number of arguments, we * reset the argument bookkeeping after each group. We reset * phase to 1, 2, or 3 after seeing the first pair, so we can tell * whether there were any arguments at all. (1 means no parameter * changed, >1 means some parameter changed.) */ pcl_font_selection_t *pfs = &pgls->g.font_selection[index]; #define pfp (&pfs->params) int kind; pfs->selected_id = (uint) - 1; for (; hpgl_arg_c_int(pgls->memory, pargs, &kind); pargs->phase |= 1) switch (kind) { case 1: /* symbol set */ { int32 sset; if (!hpgl_arg_int(pgls->memory, pargs, &sset)) return e_Range; if (pfp->symbol_set != (uint) sset) pfp->symbol_set = (uint) sset, pargs->phase |= 2; } break; case 2: /* spacing */ { int spacing; if (!hpgl_arg_c_int(pgls->memory, pargs, &spacing)) return e_Range; if (((spacing == 1) || (spacing == 0)) && (pfp->proportional_spacing != spacing)) pfp->proportional_spacing = spacing, pargs->phase |= 2; } break; case 3: /* pitch */ { hpgl_real_t pitch; if (!hpgl_arg_c_real(pgls->memory, pargs, &pitch)) return e_Range; if ((pl_fp_pitch_per_inch(pfp) != pitch) && (pitch >= 0) && (pitch < 32768.0)) { pl_fp_set_pitch_per_inch(pfp, pitch > 7200.0 ? 7200.0 : pitch); pargs->phase |= 2; } } break; case 4: /* height */ { hpgl_real_t height; if (!hpgl_arg_c_real(pgls->memory, pargs, &height)) return e_Range; if ((pfp->height_4ths != (uint) (height * 4)) && (height >= 0)) { /* minimum height for practical purposes is one quarter point. The HP Spec says 0 is legal but does not specify what a height of zero means. The previous code truncated height, it probably should be rounded as in pcl but doing so would change a lot of files for no compelling reason so for now truncate. */ uint trunc_height_4ths = (uint) (height * 4); pfp->height_4ths = (trunc_height_4ths == 0 ? 1 : trunc_height_4ths); pargs->phase |= 2; } } break; case 5: /* posture */ { int posture; if (!hpgl_arg_c_int(pgls->memory, pargs, &posture)) return e_Range; if (pfp->style != posture) pfp->style = posture, pargs->phase |= 2; } break; case 6: /* stroke weight */ { int weight; if (!hpgl_arg_c_int(pgls->memory, pargs, &weight)) return e_Range; if (pfp->stroke_weight != weight) if (((weight >= -7) && (weight <= 7)) || (weight == 9999)) pfp->stroke_weight = weight, pargs->phase |= 2; } break; case 7: /* typeface */ { int32 face; if (!hpgl_arg_int(pgls->memory, pargs, &face)) return e_Range; if (pfp->typeface_family != (uint) face) pfp->typeface_family = (uint) face, pargs->phase |= 2; } break; default: return e_Range; } /* If there were no arguments at all, default all values. */ if (!pargs->phase) hpgl_default_font_params(pfs); if (pargs->phase != 1) { /* A value changed, or we are defaulting. Decache the font. */ pfs->font = 0; if (index == pgls->g.font_selected) pgls->g.font = 0; } return 0; }