Index: parse.c =================================================================== --- parse.c (revision 11225) +++ parse.c (revision 11226) @@ -21,6 +21,7 @@ */ #include +#include #include #include "libuhpgl.h" #include "parse.h" @@ -27,6 +28,31 @@ #define inst2num(s1, s2) ((((int)s1) << 8) | (int)s2) +#define CONST_PI 3.14159265358979323846 +#define RAD2DEG(r) ((r) * 180.0 / CONST_PI) +#define DEG2RAD(d) ((d) * CONST_PI / 180.0) +#define DDIST(dx, dy) sqrt((double)(dx)*(double)(dx) + (double)(dy)*(double)(dy)) + + +/* Implementation idea borrowed from an old gcc */ +static double ROUND(double x) +{ + double t; + + if (x >= 0.0) { + t = ceil(x); + if (t - x > 0.5) + t -= 1.0; + return t; + } + + t = ceil(-x); + if ((t + x) > 0.5) + t -= 1.0; + return -t; +} + + typedef enum state_e { ST_IDLE, ST_INST, @@ -144,6 +170,7 @@ static int draw_arc_(uhpgl_ctx_t *ctx, uhpgl_arc_t *arc) { +#warning TODO: set cursor to the end if (ctx->conf.arc != NULL) return ctx->conf.arc(ctx, arc); #warning TODO: line approx @@ -150,7 +177,27 @@ return -1; } +static int draw_arc(uhpgl_ctx_t *ctx, uhpgl_coord_t cx, uhpgl_coord_t cy, double da, uhpgl_coord_t res) +{ + uhpgl_arc_t arc; + arc.pen = ctx->state.pen; + arc.center.x = cx; + arc.center.y = cy; + arc.startp.x = ctx->state.at.x; + arc.startp.y = ctx->state.at.y; + arc.r = ROUND(DDIST(arc.startp.y - arc.center.y, arc.startp.x - arc.center.x)); + arc.deltaa = da; + arc.starta = RAD2DEG(atan2(arc.startp.y - arc.center.y, arc.startp.x - arc.center.x)); + arc.enda = arc.starta + da; + + arc.endp.x = ROUND((double)cx + arc.r * cos(arc.enda)); + arc.endp.y = ROUND((double)cy + arc.r * sin(arc.enda)); + + return draw_arc_(ctx, &arc); +} + + static int draw_circ(uhpgl_ctx_t *ctx, uhpgl_coord_t cx, uhpgl_coord_t cy, uhpgl_coord_t r, uhpgl_coord_t res) { uhpgl_arc_t arc; @@ -261,10 +308,20 @@ return -1; } return 0; -/* case inst2num('A','A'): + if ((p->nums == 4) || (is_last)) { + p->state = ST_INST_END; + if (draw_arc(ctx, p->num[0], p->num[1], p->num[2], (p->nums == 4 ? p->num[3] : -1)) < 0) + return -1; + } + return 0; case inst2num('A','R'): -*/ + if ((p->nums == 4) || (is_last)) { + p->state = ST_INST_END; + if (draw_arc(ctx, ctx->state.at.x + p->num[0], ctx->state.at.y + p->num[1], p->num[2], (p->nums == 4 ? p->num[3] : -1)) < 0) + return -1; + } + return 0; } return error(ctx, "unimplemented coord instruction"); }