diff options
-rw-r--r-- | pcl/news-pcl | 23 | ||||
-rw-r--r-- | pcl/pcl.mak | 4 | ||||
-rw-r--r-- | pcl/pconf5.h | 34 | ||||
-rw-r--r-- | pcl/pconfig.h | 34 | ||||
-rw-r--r-- | pcl/pgdraw.c | 110 | ||||
-rw-r--r-- | pcl/pggeom.c | 18 | ||||
-rw-r--r-- | pcl/pggeom.h | 7 | ||||
-rw-r--r-- | pcl/pglabel.c | 11 | ||||
-rw-r--r-- | pcl/pglfill.c | 35 | ||||
-rw-r--r-- | pcl/pgstate.h | 17 | ||||
-rw-r--r-- | pcl/pgvector.c | 112 |
11 files changed, 304 insertions, 101 deletions
diff --git a/pcl/news-pcl b/pcl/news-pcl index d15763c5e..4fd3f46ea 100644 --- a/pcl/news-pcl +++ b/pcl/news-pcl @@ -6,10 +6,11 @@ This file, NEWS-PCL, describes the changes in the most recent releases of Aladdin's PCL5 code, in reverse chronological order. -Version 0.23 (4/16/97) -====================== +Version 0.24 (5/7/97) +===================== -More bug fixes. Labels now appear in the correct place. +More bug fixes. This is an intermediate fileset to synchronize LPD's and +HAS's changes. Known problems (PCL): - The width of Intellifont characters is wrong. (CET 14_01) @@ -27,6 +28,22 @@ Unimplemented features (PCL): - Text clipping at the right margin. - User-defined line type (99). +(LPD) Fixes bugs: + - The makefile rule for pcl5.dev had a typo (PCLOJB for PCLOBJ). +(pcl.mak) + +(LPD) Makes stick font characters always use round caps and joins, for +visual consistency. (pgdraw.h, pgdraw.c, pglabel.c) + +(HAS) Numerous fixes to graphics -- changes will be included in the log for +the next fileset. (pggeom.h, pgstate.h, pggeom.c, pgdraw.c, pglfill.c, +pgvector.c) + +Version 0.23 (4/16/97) +====================== + +More bug fixes. Labels now appear in the correct place. + (LPD) Splits off functionality from two existing files: - pcfont.c => pcfsel.h, pcfsel.c (font selection machinery used by both PCL and HP-GL/2) diff --git a/pcl/pcl.mak b/pcl/pcl.mak index 02fb0adf3..a12821612 100644 --- a/pcl/pcl.mak +++ b/pcl/pcl.mak @@ -303,7 +303,7 @@ PCL5_OPS=$(PCL5_OPS1) $(PCL5_OPS2) $(PCL5_OPS3) $(PCL5_OPS4) # Note: we have to initialize the cursor after initializing the logical # page dimensions, so we do it last. This is a hack. $(PCLOBJ)pcl5.dev: $(PCL_MAK) $(ECHOGS_XE) $(PCL_COMMON) $(PCL5_OPS) $(PCLOBJ)pcl5base.dev $(PCLOBJ)rtlbase.dev - $(SETMOD) $(PCLOJB)pcl5 $(PCL_COMMON) + $(SETMOD) $(PCLOBJ)pcl5 $(PCL_COMMON) $(ADDMOD) $(PCLOBJ)pcl5 $(PCL5_OPS1) $(ADDMOD) $(PCLOBJ)pcl5 $(PCL5_OPS2) $(ADDMOD) $(PCLOBJ)pcl5 $(PCL5_OPS3) @@ -356,7 +356,7 @@ $(PCLOBJ)pcl5c.dev: $(PCL_MAK) $(ECHOGS_XE) $(PCL5C_OPS) $(PCLOBJ)pcl5.dev $(PCL pgdraw_h=$(PCLSRC)pgdraw.h pgfont_h=$(PCLSRC)pgfont.h $(stdpre_h) $(gstypes_h) -pggeom_h=$(PCLSRC)pggeom.h $(math__h) +pggeom_h=$(PCLSRC)pggeom.h $(math__h) $(gstypes_h) pginit_h=$(PCLSRC)pginit.h pgmisc_h=$(PCLSRC)pgmisc.h diff --git a/pcl/pconf5.h b/pcl/pconf5.h new file mode 100644 index 000000000..f8defd73a --- /dev/null +++ b/pcl/pconf5.h @@ -0,0 +1,34 @@ +/* This file was generated automatically by genconf.c. */ +#ifdef init_ +init_(pcparse_init) +init_(rtmisc_init) +init_(rtcursor_init) +init_(rtraster_init) +init_(pcjob_init) +init_(pcpage_init) +init_(pcdraw_init) +init_(pcfont_init) +init_(pcsymbol_init) +init_(pcsfont_init) +init_(pcmacros_init) +init_(pcprint_init) +init_(pcrect_init) +init_(rtraster_pcl_init) +init_(pcstatus_init) +init_(pcmisc_init) +init_(pcursor_init) +init_(rtcolor_init) +init_(rtcrastr_init) +init_(pccpalet_init) +init_(pccrendr_init) +init_(pccprint_init) +init_(rtcrastr_pcl_init) +init_(pginit_init) +init_(pgframe_init) +init_(pgconfig_init) +init_(pgvector_init) +init_(pgpoly_init) +init_(pglfill_init) +init_(pgchar_init) +init_(pglabel_init) +#endif diff --git a/pcl/pconfig.h b/pcl/pconfig.h new file mode 100644 index 000000000..f8defd73a --- /dev/null +++ b/pcl/pconfig.h @@ -0,0 +1,34 @@ +/* This file was generated automatically by genconf.c. */ +#ifdef init_ +init_(pcparse_init) +init_(rtmisc_init) +init_(rtcursor_init) +init_(rtraster_init) +init_(pcjob_init) +init_(pcpage_init) +init_(pcdraw_init) +init_(pcfont_init) +init_(pcsymbol_init) +init_(pcsfont_init) +init_(pcmacros_init) +init_(pcprint_init) +init_(pcrect_init) +init_(rtraster_pcl_init) +init_(pcstatus_init) +init_(pcmisc_init) +init_(pcursor_init) +init_(rtcolor_init) +init_(rtcrastr_init) +init_(pccpalet_init) +init_(pccrendr_init) +init_(pccprint_init) +init_(rtcrastr_pcl_init) +init_(pginit_init) +init_(pgframe_init) +init_(pgconfig_init) +init_(pgvector_init) +init_(pgpoly_init) +init_(pglfill_init) +init_(pgchar_init) +init_(pglabel_init) +#endif diff --git a/pcl/pgdraw.c b/pcl/pgdraw.c index ad837b4de..a000434a2 100644 --- a/pcl/pgdraw.c +++ b/pcl/pgdraw.c @@ -31,7 +31,7 @@ Potential performance issue. The design choice is based solely on ease of implementation. */ -private int + private int hpgl_set_graphics_dash_state(hpgl_state_t *pgls) { bool adaptive = ( pgls->g.line.type < 0 ); @@ -85,7 +85,7 @@ hpgl_set_graphics_dash_state(hpgl_state_t *pgls) } /* set up joins, caps, miter limit, and line width */ -private int + private int hpgl_set_graphics_line_attribute_state(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) { @@ -144,7 +144,7 @@ vector: hpgl_call(gs_setlinejoin(pgls->pgs, } /* set up an hpgl clipping region wrt last IW command */ -private int + private int hpgl_set_clipping_region(hpgl_state_t *pgls) { gs_fixed_rect fixed_box; @@ -168,7 +168,7 @@ hpgl_set_clipping_region(hpgl_state_t *pgls) return 0; } -private int + private int hpgl_set_plu_to_device_ctm(hpgl_state_t *pgls) { pcl_set_ctm(pgls, false); @@ -230,7 +230,7 @@ hpgl_set_plu_to_device_ctm(hpgl_state_t *pgls) return 0; } -private int + private int hpgl_set_label_to_plu_ctm(hpgl_state_t *pgls) { /* if we are not in character mode do nothing -- identity @@ -240,9 +240,7 @@ hpgl_set_label_to_plu_ctm(hpgl_state_t *pgls) &pgls->g.font_selection[pgls->g.font_selected]; hpgl_real_t height_points = pfs->params.height_4ths / 4.0; hpgl_real_t width_points = 1.0 / (pfs->params.pitch_100ths / 100.0); - /* HAS -- Only LO1 is currently supported -- need to add others */ hpgl_call(gs_translate(pgls->pgs, pgls->g.pos.x, pgls->g.pos.y)); - /* HAS -- only support standard font */ hpgl_call(gs_scale(pgls->pgs, points_2_plu(height_points), inches_2_plu(width_points))); @@ -250,31 +248,32 @@ hpgl_set_label_to_plu_ctm(hpgl_state_t *pgls) } -private int + private int hpgl_set_user_units_to_plu_ctm(hpgl_state_t *pgls) { - hpgl_call(gs_translate(pgls->pgs, pgls->g.P1.x, -pgls->g.P1.y)); + hpgl_call(gs_translate(pgls->pgs, pgls->g.P1.x, pgls->g.P1.y)); /* finally scale to user units. HAS this only handles the simple scaling scale for the moment. */ - if ( pgls->g.scaling_type == hpgl_scaling_anisotropic ) - { + /* if ( pgls->g.scaling_type == hpgl_scaling_anisotropic ) */ + if ( pgls->g.scaling_type != hpgl_scaling_none ) + { floatp scale_x = (pgls->g.P2.x - pgls->g.P1.x) / (pgls->g.scaling_params.pmax.x - pgls->g.scaling_params.pmin.x); floatp scale_y = (pgls->g.P2.y - pgls->g.P1.y) / (pgls->g.scaling_params.pmax.y - pgls->g.scaling_params.pmin.y); hpgl_call(gs_scale(pgls->pgs, scale_x, scale_y)); } - else if ( pgls->g.scaling_type != hpgl_scaling_none ) - dprintf1("unsuported scaling type %d:\n", pgls->g.scaling_type); + /* else if ( pgls->g.scaling_type != hpgl_scaling_none ) */ + /* dprintf1("unsuported scaling type %d:\n", pgls->g.scaling_type); */ return 0; } /* set up ctm's. Uses the current render mode to figure out which ctm is appropriate */ -private int + private int hpgl_set_ctm(hpgl_state_t *pgls) { /* convert pcl->device to plu->device */ @@ -291,30 +290,50 @@ hpgl_set_ctm(hpgl_state_t *pgls) } /* maps current hpgl fill type to pcl pattern type. */ -private pcl_pattern_type_t -hpgl_map_fill_type(hpgl_state_t *pgls) + private pcl_pattern_type_t +hpgl_map_fill_type(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) { - switch (pgls->g.fill.type) + + if ( render_mode == hpgl_rm_character ) { - case hpgl_fill_solid : return pcpt_solid_black; - case hpgl_fill_solid2 : return pcpt_solid_black; - case hpgl_fill_pcl_crosshatch : return pcpt_cross_hatch; - case hpgl_fill_shaded : return pcpt_shading; - case hpgl_fill_pcl_user_defined : - dprintf("No key mapping support falling back to solid\n"); - break; - default : - dprintf1("Unsupported fill type %d falling back to solid\n", - pgls->g.fill.type); + switch (pgls->g.character.fill_mode) + { + case 0 : ; return pcpt_solid_black; + case 1 : ; /* HAS NOT IMPLEMENTED */ + case 2 : ; /* HAS NOT IMPLEMENTED */ + case 3 : ; /* HAS NOT IMPLEMENTED */ + dprintf1("Character fill mode %d not supported falling back to solid\n", + pgls->g.character.fill_mode); + break; + default : + dprintf1("Unknown character fill mode falling back to solid%d\n", + pgls->g.character.fill_mode); + break; + } + } + else + { + switch (pgls->g.fill.type) + { + case hpgl_fill_solid : return pcpt_solid_black; + case hpgl_fill_solid2 : return pcpt_solid_black; + case hpgl_fill_pcl_crosshatch : return pcpt_cross_hatch; + case hpgl_fill_shaded : return pcpt_shading; + case hpgl_fill_pcl_user_defined : + dprintf("No key mapping support falling back to solid\n"); + break; + default : + dprintf1("Unsupported fill type %d falling back to solid\n", + pgls->g.fill.type); + } } - return pcpt_solid_black; } /* HAS I don't much care for the idea of overloading pcl_id with shading and hatching information, but that appears to be the way pcl_set_drawing_color() is set up. */ -private pcl_id_t * + private pcl_id_t * hpgl_map_id_type(hpgl_state_t *pgls, pcl_id_t *id) { switch (pgls->g.fill.type) @@ -341,13 +360,13 @@ hpgl_map_id_type(hpgl_state_t *pgls, pcl_id_t *id) return id; } -private int -hpgl_set_drawing_color(hpgl_state_t *pgls) + private int +hpgl_set_drawing_color(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) { pcl_id_t pcl_id; hpgl_call(pcl_set_drawing_color(pgls, - hpgl_map_fill_type(pgls), + hpgl_map_fill_type(pgls, render_mode), hpgl_map_id_type(pgls, &pcl_id))); return 0; } @@ -368,7 +387,7 @@ hpgl_set_graphics_state(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) hpgl_call(hpgl_set_graphics_line_attribute_state(pgls, render_mode)); /* set up the hpgl fills. */ - hpgl_call(hpgl_set_drawing_color(pgls)); + hpgl_call(hpgl_set_drawing_color(pgls, render_mode)); /* set up a clipping region */ hpgl_call(hpgl_set_clipping_region(pgls)); @@ -376,7 +395,7 @@ hpgl_set_graphics_state(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) return 0; } -int + int hpgl_get_current_position(hpgl_state_t *pgls, gs_point *pt) { @@ -384,7 +403,7 @@ hpgl_get_current_position(hpgl_state_t *pgls, gs_point *pt) return 0; } -int + int hpgl_set_current_position(hpgl_state_t *pgls, gs_point *pt) { if ( pgls->g.relative ) @@ -424,7 +443,7 @@ hpgl_start_path(hpgl_state_t *pgls, gs_point pt) return 0; } -int + int hpgl_add_point_to_path(hpgl_state_t *pgls, floatp x, floatp y, int (*gs_func)(gs_state *pgs, floatp x, floatp y)) { @@ -451,7 +470,7 @@ hpgl_add_point_to_path(hpgl_state_t *pgls, floatp x, floatp y, /* destroys the current path. HAS probably don't need to create a new one also. */ -int + int hpgl_clear_current_path(hpgl_state_t *pgls) { /* if a current path exists set the current state position */ @@ -461,7 +480,7 @@ hpgl_clear_current_path(hpgl_state_t *pgls) } /* closes the current path, making the first point and last point coincident */ -int + int hpgl_close_current_path(hpgl_state_t *pgls) { hpgl_call(gs_closepath(pgls->pgs)); @@ -469,7 +488,7 @@ hpgl_close_current_path(hpgl_state_t *pgls) } /* converts pcl coordinate to device space and back to hpgl space */ -int + int hpgl_add_pcl_point_to_path(hpgl_state_t *pgls, gs_point *pcl_pt) { gs_point dev_pt, hpgl_pt; @@ -481,7 +500,8 @@ hpgl_add_pcl_point_to_path(hpgl_state_t *pgls, gs_point *pcl_pt) hpgl_call(hpgl_add_point_to_path(pgls, hpgl_pt.x, hpgl_pt.y, gs_moveto)); return 0; } -int + + int hpgl_add_arc_to_path(hpgl_state_t *pgls, floatp center_x, floatp center_y, floatp radius, floatp start_angle, floatp sweep_angle, floatp chord_angle) @@ -520,7 +540,7 @@ hpgl_add_arc_to_path(hpgl_state_t *pgls, floatp center_x, floatp center_y, return 0; } -int + int hpgl_add_bezier_to_path(hpgl_state_t *pgls, floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3, floatp x4, floatp y4) @@ -540,7 +560,7 @@ hpgl_add_bezier_to_path(hpgl_state_t *pgls, floatp x1, floatp y1, /* an implicit gl/2 style closepath. If the first and last point are the same the path gets closed */ -private int + private int hpgl_close_path(hpgl_state_t *pgls) { gs_point last_point; @@ -559,7 +579,7 @@ hpgl_close_path(hpgl_state_t *pgls) extraneous PU's do not result in separate subpaths. */ /* Stroke the current path */ -int + int hpgl_draw_current_path(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) { if ( !pgls->g.have_first_moveto ) return 0; @@ -584,7 +604,7 @@ hpgl_draw_current_path(hpgl_state_t *pgls, hpgl_rendering_mode_t render_mode) return 0; } -int + int hpgl_draw_line(hpgl_state_t *pgls, floatp x1, floatp y1, floatp x2, floatp y2) { hpgl_call(hpgl_add_point_to_path(pgls, x1, y1, @@ -597,7 +617,7 @@ hpgl_draw_line(hpgl_state_t *pgls, floatp x1, floatp y1, floatp x2, floatp y2) return 0; } -int + int hpgl_draw_dot(hpgl_state_t *pgls, floatp x1, floatp y1) { hpgl_call(hpgl_add_point_to_path(pgls, x1, y1, diff --git a/pcl/pggeom.c b/pcl/pggeom.c index 584304a35..fb37b47d9 100644 --- a/pcl/pggeom.c +++ b/pcl/pggeom.c @@ -97,7 +97,7 @@ hpgl_compute_arc_center(floatp x1, floatp y1, floatp x2, floatp y2, * y = (a*f - c*d) / denom */ denom = dx3 * dy2 - dx2 * dy3; - if ( denom < 1.0e-6 ) + if ( fabs(denom) < 1.0e-6 ) return -1; /* degenerate */ t2 = ((px3 - px2) * (-dy3) - (-dx3) * (py3 - py2)) / denom; @@ -136,3 +136,19 @@ hpgl_compute_vector_endpoints(floatp magnitude, floatp x, floatp y, angle_degrees * (M_PI/180.0), endx, endy); } + + int +hpgl_compute_dot_product(gs_point *pt1, gs_point *pt2, floatp *result) +{ + *result = ((pt1->x * pt2->x) + (pt1->y * pt2->y)); + return 0; +} + +/* scales a 2d vector */ + int +hpgl_scale_vector(gs_point *pt1, floatp scale, gs_point *result) +{ + result->x = scale * pt1->x; + result->y = scale * pt1->y; + return 0; +} diff --git a/pcl/pggeom.h b/pcl/pggeom.h index 3686ad088..b565f1a5a 100644 --- a/pcl/pggeom.h +++ b/pcl/pggeom.h @@ -9,6 +9,7 @@ # define pggeom_INCLUDED #include "math_.h" +#include "gstypes.h" /* for gs_point */ /* ------ Useful conversions ------ */ @@ -61,6 +62,12 @@ int hpgl_compute_vector_endpoints(P6(floatp magnitude, floatp x, floatp y, floatp angle_degrees, floatp *endx, floatp *endy)); +/* calculates the dot product of 2 2d vectors */ +int hpgl_compute_dot_product(P3(gs_point *pt1, gs_point *pt2, floatp *result)); + +/* scales a 2d vector */ +int hpgl_scale_vector(P3(gs_point *pt1, floatp scale, gs_point *result)); + /* ------ 3-point arcs ------ */ /* points are equal. HAS -- TEST for epsilon */ diff --git a/pcl/pglabel.c b/pcl/pglabel.c index 8ac7b45e7..330ddd146 100644 --- a/pcl/pglabel.c +++ b/pcl/pglabel.c @@ -15,6 +15,7 @@ #include "pggeom.h" #include "pgmisc.h" #include "pcfsel.h" +#include "gsline.h" /* Define a bogus pl_font_t for the stick font. */ /* Eventually this will be a real one.... */ @@ -270,6 +271,10 @@ hpgl_print_char(hpgl_state_t *pgls, hpgl_character_point *character) pgls->g.current_render_mode = hpgl_rm_character; hpgl_call(hpgl_set_graphics_state(pgls, hpgl_rm_character)); + /* Always use round caps and joins. */ + gs_setlinecap(pgls->pgs, gs_cap_round); + gs_setlinejoin(pgls->pgs, gs_join_round); + /* all character data is absolute */ pgls->g.relative = false; while (character->operation != hpgl_char_end) @@ -513,10 +518,12 @@ shift: hpgl_call(hpgl_recompute_font(pgls)); do_CR = true; break; case FF : - /****** WHAT TO DO? ******/ + /* does nothing */ + spaces = 0, lines = 0; break; case HT : - /****** WHAT TO DO? ******/ + /* appears to expand to 5 spaces */ + spaces = 5, lines = 0; break; case SI : pgls->g.font_selected = 0; diff --git a/pcl/pglfill.c b/pcl/pglfill.c index 1fe47e4b4..70a4ad6af 100644 --- a/pcl/pglfill.c +++ b/pcl/pglfill.c @@ -199,20 +199,33 @@ private const hpgl_line_type_t hpgl_adaptive_pats[8] = { /* LT; */ int hpgl_LT(hpgl_args_t *pargs, hpgl_state_t *pgls) -{ int type = 0; +{ + int type = 0; if ( hpgl_arg_c_int(pargs, &type) ) - { if ( type == 99 ) - ; + { + /* restore old saved line if we have a solid line, + otherwise the instruction is ignored. */ + if ( type == 99 ) + { + if ( pgls->g.line.is_solid == true ) + { + hpgl_args_t args; + hpgl_args_set_int(&args, pgls->g.line.last_type); + hpgl_LT(&args, pgls); + } + return 0; + } else - { hpgl_real_t length = 0.04; - int mode = 0; + { + hpgl_real_t length = 0.04; + int mode = 0; if ( type < -8 || type > 8 || (hpgl_arg_c_real(pargs, &length) && (length <= 0 || (hpgl_arg_c_int(pargs, &mode) && (mode & ~1)))) - ) + ) return e_Range; pgls->g.line.pattern_length = length; pgls->g.line.pattern_length_relative = mode == 0; @@ -220,8 +233,12 @@ hpgl_LT(hpgl_args_t *pargs, hpgl_state_t *pgls) } } else { - /* no args restore defaults */ - /*** HAS, need to save the current line type also ***/ + /* no args restore defaults and set previous line + type. */ + /* HAS **BUG**BUG** initial value of line type + is not supplied unless it gets set by previous LT + command. */ + pgls->g.line.last_type = pgls->g.line.type; pgls->g.line.is_solid = true; memcpy(&pgls->g.fixed_line_type, &hpgl_fixed_pats, @@ -458,7 +475,7 @@ hpgl_UL(hpgl_args_t *pargs, hpgl_state_t *pgls) hpgl_line_type_t *fixed_plt = &pgls->g.fixed_line_type[(index < 0 ? -index : index) - 1]; hpgl_line_type_t *adaptive_plt = - &pgls->g.fixed_line_type[(index < 0 ? -index : index) - 1]; + &pgls->g.adaptive_line_type[(index < 0 ? -index : index) - 1]; fixed_plt->count = adaptive_plt->count = i; memcpy(fixed_plt->gap, gap, i * sizeof(hpgl_real_t)); memcpy(adaptive_plt->gap, gap, i * sizeof(hpgl_real_t)); diff --git a/pcl/pgstate.h b/pcl/pgstate.h index 4e0e74b32..84446915f 100644 --- a/pcl/pgstate.h +++ b/pcl/pgstate.h @@ -8,6 +8,15 @@ #ifndef pgstate_INCLUDED # define pgstate_INCLUDED +/* HPGL/2 coordinates are internally represented in plotter units + 1/1024" when scaling is off and user units when scaling is in + effect. The data structure g.pos maintains the coordinates in the + hpgl/2 state. By default the coordinate system sets up the origin + in the lower left of the page with X increasing along the short + edge and Y increasing up the long edge. Note the Y direction is + opposite PCL's. */ + + #include "gslparam.h" #include "gsuid.h" /* for gxbitmap.h */ #include "gstypes.h" /* for gxbitmap.h */ @@ -95,6 +104,7 @@ typedef struct pcl_hpgl_state_s { /* Chapter 22 (pglfill.c) */ struct lp_ { + int last_type; /* used by line type 99 */ int type; float pattern_length; bool pattern_length_relative; @@ -237,4 +247,11 @@ do {\ if ( (restore_flags) & hpgl_pen_pos )\ ((pgls)->g.pos = (save)->pos);\ } while (0) + +/* save the current line to be used when lt99 is issued */ +#define hpgl_set_line_type99(pgls) ((pgls)->g.line99 = (pgls)->g.line) + +/* restore previous line type */ +#define hpgl_restore_line_type99(pgls) ((pgls)->g.line = (pgls)->g.line99) #endif /* pgstate_INCLUDED */ + diff --git a/pcl/pgvector.c b/pcl/pgvector.c index 13978790c..d3bda37d0 100644 --- a/pcl/pgvector.c +++ b/pcl/pgvector.c @@ -46,11 +46,13 @@ hpgl_arc(hpgl_args_t *pargs, hpgl_state_t *pgls, bool relative) radius = hpgl_compute_distance(x_current, y_current, x_center, y_center); - start_angle = + start_angle = radians_to_degrees * hpgl_compute_angle(x_current - x_center, y_current - y_center); hpgl_add_arc_to_path(pgls, x_center, y_center, - radius, start_angle, sweep, chord_angle); + radius, start_angle, sweep, + (sweep < 0.0 ) ? + -chord_angle : chord_angle); hpgl_draw_current_path(pgls, hpgl_rm_vector); @@ -88,10 +90,7 @@ hpgl_arc_3_point(hpgl_args_t *pargs, hpgl_state_t *pgls, bool relative) x_start = pgls->g.pos.x; y_start = pgls->g.pos.y; - - /* HAS check this */ - /* hpgl_draw_current_path(pgls, hpgl_rm_vector); */ - + if ( hpgl_3_same_points(x_start, y_start, x_inter, y_inter, x_end, y_end) ) hpgl_draw_dot(pgls, x_start, y_start); @@ -127,24 +126,70 @@ hpgl_arc_3_point(hpgl_args_t *pargs, hpgl_state_t *pgls, bool relative) x_inter, y_inter, x_end, y_end, &x_center, &y_center); - radius = hpgl_compute_distance(x_start, y_start, - x_center, y_center); + radius = hypot(x_start - x_center, y_start - y_center); counter_clockwise = - hpgl_compute_arc_direction(x_start, y_start, x_end, y_end); + hpgl_compute_arc_direction(x_start, y_start, x_inter, y_inter); - start_angle = + start_angle = radians_to_degrees * hpgl_compute_angle(x_start - x_center, y_start - y_center); - end_angle = + end_angle = radians_to_degrees * hpgl_compute_angle(x_end - x_center, y_end - y_center); - hpgl_add_arc_to_path(pgls, x_center, y_center, radius, - start_angle, - (counter_clockwise ? - -(end_angle - start_angle) : - (start_angle - end_angle)), - chord_angle); + { + floatp sweep_angle, dot_product; + hpgl_args_t args; + gs_point u, v, u_scaled, v_scaled; + + /* calculate angle x between start vector (u) and end vector + (v) using: + u v + cos(x) =---- . ---- + ||u|| ||v|| + */ + + u.x = x_start - x_center; + u.y = y_start - y_center; + + v.x = x_end - x_center; + v.y = y_end - y_center; + + hpgl_call(hpgl_scale_vector(&u, (1.0 / radius), &u_scaled)); + hpgl_call(hpgl_scale_vector(&v, (1.0 / radius), &v_scaled)); + + hpgl_call(hpgl_compute_dot_product(&u_scaled, + &v_scaled, + &dot_product)); + + /* HAS annoying imprecision -- clamp for now but needs + to be done correctly later specifically dot_product + +- NOISE results in acos returning NaN */ + dot_product = (dot_product > 1.0) ? 1.0 : dot_product; + dot_product = (dot_product < -1.0) ? -1.0 : dot_product; + sweep_angle = radians_to_degrees * acos(dot_product); + + + + if ( hpgl_compute_arc_direction(x_start, y_start, + x_inter, y_inter) ) + { + sweep_angle = -sweep_angle; + sweep_angle += 360.0; + sweep_angle = -sweep_angle; + } + else + sweep_angle = 360.0 - sweep_angle; + + /* reverse the direction if necessary. hpgl_arc handles + changing the chord value. */ + + hpgl_args_set_real(&args, x_center); + hpgl_args_add_real(&args, y_center); + hpgl_args_add_real(&args, sweep_angle); + hpgl_args_add_real(&args, chord_angle); + hpgl_arc(&args, pgls, false); + } } return 0; } @@ -293,35 +338,24 @@ int hpgl_CI(hpgl_args_t *pargs, hpgl_state_t *pgls) { hpgl_real_t radius, chord = 5; + hpgl_pen_state_t saved_pen_state; if ( !hpgl_arg_units(pargs, &radius) ) return e_Range; hpgl_arg_c_real(pargs, &chord); - { - hpgl_args_t args; - bool down = pgls->g.pen_down; + /* draw the current path if there is one */ + hpgl_draw_current_path(pgls, hpgl_rm_vector); + hpgl_save_pen_state(pgls, &saved_pen_state, hpgl_pen_all); - hpgl_clear_current_path(pgls); + pgls->g.pen_down = true; - /* implicit pen down */ - hpgl_args_setup(&args); - hpgl_PU(&args, pgls); + /* draw the arc/circle */ + hpgl_add_arc_to_path(pgls, pgls->g.pos.x, pgls->g.pos.y, + radius, 0.0, 360.0, chord); + /* restore pen state */ - hpgl_args_setup(&args); - hpgl_PD(&args, pgls); + hpgl_restore_pen_state(pgls, &saved_pen_state, hpgl_pen_all); + hpgl_draw_current_path(pgls, hpgl_rm_vector); - /* draw the arc/circle */ - hpgl_add_arc_to_path(pgls, pgls->g.pos.x, pgls->g.pos.y, - radius, 0.0, 360.0, chord); - /* restore pen state */ - hpgl_args_setup(&args); - if (down) - hpgl_PD(&args, pgls); - else - hpgl_PU(&args, pgls); - } - - /* HAS check this */ - /* hpgl_draw_current_path(pgls, hpgl_rm_vector); */ return 0; } |