/* DL [Character Code, Coords] */ int hpgl_DL(hpgl_args_t * pargs, hpgl_state_t * pgls) { int code; hpgl_dl_cdata_t *cdata; /* first call */ if (pargs->phase == 0) { int32 cc; /* double byte characters are not yet supported */ if (pgls->g.label.double_byte) return e_Unimplemented; /* parse the character code, no arguments clears all defined characters */ if (!hpgl_arg_c_int(pgls->memory, pargs, &cc)) { hpgl_clear_dl_chars(pgls); return 0; } if (cc < 0 || cc > 255) return e_Range; cdata = (hpgl_dl_cdata_t *) gs_alloc_bytes(pgls->memory, sizeof(hpgl_dl_cdata_t), "DL header"); if (cdata == 0) return e_Memory; cdata->index = -1; cdata->data = NULL; id_set_value(pgls->g.current_dl_char_id, (ushort) cc); pl_dict_put(&pgls->g.dl_531_fontdict, id_key(pgls->g.current_dl_char_id), 2, cdata); hpgl_args_init(pargs); pargs->phase = 1; } if (!pl_dict_find (&pgls->g.dl_531_fontdict, id_key(pgls->g.current_dl_char_id), 2, (void **)&cdata)) /* this should be a failed assertion */ return -1; do { int c; if (!hpgl_arg_c_int(pgls->memory, pargs, &c)) break; code = hpgl_add_dl_char_data(pgls, cdata, c); if (code < 0) { pl_dict_undef(&pgls->g.dl_531_fontdict, id_key(pgls->g.current_dl_char_id), 2); return code; } hpgl_args_init(pargs); } while (1); 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; }
/* 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; }
/* SB [mode]; */ int hpgl_SB(hpgl_args_t * pargs, hpgl_state_t * pgls) { int mode = 0; if (hpgl_arg_c_int(pgls->memory, pargs, &mode) && (mode & ~1)) return e_Range; { int i; pgls->g.bitmap_fonts_allowed = mode; /* * A different set of fonts is now available for consideration. * Decache any affected font(s): those selected by parameter, * and bitmap fonts selected by ID if bitmap fonts are now * disallowed. */ for (i = 0; i < countof(pgls->g.font_selection); ++i) { pcl_font_selection_t *pfs = &pgls->g.font_selection[i]; if (((int)pfs->selected_id < 0) || (!mode && pfs->font != 0 && pfs->font->scaling_technology == plfst_bitmap) ) { pfs->font = 0; } } pgls->g.font = 0; pgls->g.map = 0; } return 0; }
/* TD [mode]; */ int hpgl_TD(hpgl_args_t * pargs, hpgl_state_t * pgls) { int mode = 0; if (hpgl_arg_c_int(pgls->memory, pargs, &mode) && (mode & ~1)) return e_Range; pgls->g.transparent_data = mode; 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; }
/* 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; }
/* LM [mode[, row number]]; */ int hpgl_LM(hpgl_args_t * pargs, hpgl_state_t * pgls) { int mode = 0, row_number = 0; int old_mode = (pgls->g.label.double_byte ? 1 : 0) + (pgls->g.label.write_vertical ? 2 : 0); hpgl_arg_c_int(pgls->memory, pargs, &mode); hpgl_arg_c_int(pgls->memory, pargs, &row_number); pgls->g.label.row_offset = (row_number < 0 ? 0 : row_number > 255 ? 255 : row_number) << 8; mode &= 3; pgls->g.label.double_byte = (mode & 1) != 0; pgls->g.label.write_vertical = (mode & 2) != 0; /* * The documentation says "When LM switches modes, it turns off * symbol mode." We take this literally: LM only turns off * symbol mode if the new label mode differs from the old one. */ if (mode != old_mode) pgls->g.symbol_mode = 0; return 0; }
/* DT terminator[,mode]; */ int hpgl_DT(hpgl_args_t * pargs, hpgl_state_t * pgls) { const byte *p = pargs->source.ptr; const byte *rlimit = pargs->source.limit; byte ch = (byte) pargs->phase; int mode = 1; /* We use phase to remember the terminator character */ /* in case we had to restart execution. */ if (p >= rlimit) return gs_error_NeedInput; if (!ch) switch ((ch = *++p)) { case ';': pargs->source.ptr = p; pgls->g.label.terminator = 3; pgls->g.label.print_terminator = false; return 0; case 0: case 5: case 27: return e_Range; default: if (p >= rlimit) return gs_error_NeedInput; if (*++p == ',') { pargs->source.ptr = p; pargs->phase = ch; if_debug1m('i', pgls->memory, "%c", ch); } } if (hpgl_arg_c_int(pgls->memory, pargs, &mode) && (mode & ~1)) return e_Range; pgls->g.label.terminator = ch; pgls->g.label.print_terminator = !mode; return 0; }
/* Select font by ID (FI, FN). */ static int hpgl_select_font_by_id(hpgl_args_t * pargs, hpgl_state_t * pgls, int index) { pcl_font_selection_t *pfs = &pgls->g.font_selection[index]; int32 id; int code; if (!hpgl_arg_c_int(pgls->memory, pargs, &id) || id < 0) return e_Range; code = pcl_select_font_by_id(pfs, id, pgls /****** NOTA BENE ******/ ); switch (code) { default: /* error */ return code; case 1: /* ID not found, no effect */ return 0; case 0: /* ID found */ break; } pgls->g.font_selection[index].font = pfs->font; pgls->g.font_selection[index].map = pfs->map; /* * If we just selected a bitmap font, force the equivalent of SB1. * See TRM 23-65 and 23-81. */ if (pfs->font->scaling_technology == plfst_bitmap) { hpgl_args_t args; hpgl_args_setup(&args); hpgl_args_add_int(&args, 1); hpgl_SB(&args, pgls); } /* note pcltrm 23-54 - only select if the table (primary or secondary) matches the currently selected table. */ if (index == pgls->g.font_selected) { hpgl_select_font(pgls, index); } return 0; }
/* * CF [mode[,pen]]; */ int hpgl_CF(hpgl_args_t * pargs, hpgl_state_t * pgls) { int mode = 0; int npen = pcl_palette_get_num_entries(pgls->ppalet); int32 pen = 0; if (hpgl_arg_c_int(pgls->memory, pargs, &mode)) { if ((mode & ~3) != 0) return e_Range; /* With only 1 argument, we "unset" the current pen. This causes the drawing machinery to use the current pen when the stroke is rendered (i.e. a subsequent SP will change the character edge pen */ if (hpgl_arg_int(pgls->memory, pargs, &pen)) { if ((pen < 0) || (pen >= npen)) return e_Range; } else pen = CHAR_EDGE_PEN_UNSET; } pgls->g.character.fill_mode = mode; pgls->g.character.edge_pen = pen; 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; }
/* 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; }