#include "hpgltops.h"
static double decode_number(unsigned char **, int, double);
static void plot_points(int, param_t *);
void
AA_arc_absolute(int num_params,
param_t *params)
{
float x, y,
dx, dy;
float start, end,
theta,
dt,
radius;
if (num_params < 3)
return;
x = Transform[0][0] * params[0].value.number +
Transform[0][1] * params[1].value.number +
Transform[0][2];
y = Transform[1][0] * params[0].value.number +
Transform[1][1] * params[1].value.number +
Transform[1][2];
dx = PenPosition[0] - x;
dy = PenPosition[1] - y;
start = (float)(180.0 * atan2(dy, dx) / M_PI);
if (start < 0.0)
start += 360.0f;
end = start + params[2].value.number;
radius = (float)hypot(dx, dy);
if (PenDown)
{
if (num_params > 3 && params[3].value.number > 0.0)
dt = (float)fabs(params[3].value.number);
else
dt = 5.0;
if (!PolygonMode)
Outputf("MP\n");
PenValid = 1;
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
if (start < end)
for (theta = start + dt; theta < end; theta += dt)
{
PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
else
for (theta = start - dt; theta > end; theta -= dt)
{
PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
}
PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
if (PenDown)
{
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
if (!PolygonMode)
Outputf("ST\n");
}
}
void
AR_arc_relative(int num_params,
param_t *params)
{
float x, y,
dx, dy;
float start, end,
theta,
dt,
radius;
if (num_params < 3)
return;
x = Transform[0][0] * params[0].value.number +
Transform[0][1] * params[1].value.number +
PenPosition[0];
y = Transform[1][0] * params[0].value.number +
Transform[1][1] * params[1].value.number +
PenPosition[1];
dx = PenPosition[0] - x;
dy = PenPosition[1] - y;
start = (float)(180.0 * atan2(dy, dx) / M_PI);
if (start < 0.0)
start += 360.0f;
end = start + params[2].value.number;
radius = (float)hypot(dx, dy);
if (PenDown)
{
if (num_params > 3 && params[3].value.number > 0.0)
dt = (float)fabs(params[3].value.number);
else
dt = 5.0;
if (!PolygonMode)
Outputf("MP\n");
PenValid = 1;
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
if (start < end)
for (theta = start + dt; theta < end; theta += dt)
{
PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
else
for (theta = start - dt; theta > end; theta -= dt)
{
PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
}
PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
if (PenDown)
{
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
if (!PolygonMode)
Outputf("ST\n");
}
}
void
AT_arc_absolute3(int num_params,
param_t *params)
{
if (num_params < 4)
return;
if (PenDown)
{
if (!PolygonMode)
Outputf("MP\n");
PenValid = 1;
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
PenPosition[0] = Transform[0][0] * params[0].value.number +
Transform[0][1] * params[1].value.number +
Transform[0][2];
PenPosition[1] = Transform[1][0] * params[0].value.number +
Transform[1][1] * params[1].value.number +
Transform[1][2];
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
PenPosition[0] = Transform[0][0] * params[2].value.number +
Transform[0][1] * params[3].value.number +
Transform[0][2];
PenPosition[1] = Transform[1][0] * params[2].value.number +
Transform[1][1] * params[3].value.number +
Transform[1][2];
if (PenDown)
{
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
if (!PolygonMode)
Outputf("ST\n");
}
}
void
CI_circle(int num_params,
param_t *params)
{
float x, y;
float theta,
dt,
radius;
if (num_params < 1)
return;
if (!PenDown)
return;
radius = params[0].value.number;
if (num_params > 1)
dt = (float)fabs(params[1].value.number);
else
dt = 5.0;
if (!PolygonMode)
Outputf("MP\n");
PenValid = 1;
for (theta = 0.0; theta < 360.0; theta += dt)
{
x = (float)(PenPosition[0] +
radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
y = (float)(PenPosition[1] +
radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
Outputf("%.3f %.3f %s\n", x, y, theta == 0.0 ? "MO" : "LI");
}
Outputf("CP\n");
if (!PolygonMode)
Outputf("ST\n");
}
void
PA_plot_absolute(int num_params,
param_t *params)
{
PenMotion = 0;
if (num_params > 1)
plot_points(num_params, params);
}
void
PD_pen_down(int num_params,
param_t *params)
{
PenDown = 1;
if (num_params > 1)
plot_points(num_params, params);
}
void
PE_polyline_encoded(int num_params,
param_t *params)
{
unsigned char *s;
int temp,
base_bits,
draw,
abscoords;
double tx, ty,
x, y,
frac_bits;
base_bits = 6;
frac_bits = 1.0;
draw = PenDown;
abscoords = 0;
if (num_params == 0)
return;
if (!PolygonMode)
{
Outputf("MP\n");
PenValid = 0;
}
if (!PenValid)
{
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
PenValid = 1;
}
for (s = (unsigned char *)params[0].value.string; *s != '\0';)
switch (*s)
{
case '7' :
s ++;
base_bits = 5;
#ifdef DEBUG
fputs("DEBUG: 7-bit\n", stderr);
#endif
Outputf("%% PE: 7-bit\n");
break;
case ':' :
s ++;
PenNumber = (int)decode_number(&s, base_bits, 1.0);
#ifdef DEBUG
fprintf(stderr, "DEBUG: set pen #%d\n", PenNumber);
#endif
Outputf("%% PE: set pen #%d\n", PenNumber);
if (PageDirty)
printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
Pens[PenNumber].width * PenScaling);
break;
case '<' :
draw = 0;
s ++;
#ifdef DEBUG
fputs("DEBUG: moveto\n", stderr);
#endif
Outputf("%% PE: moveto\n");
break;
case '>' :
s ++;
temp = (int)decode_number(&s, base_bits, 1.0);
frac_bits = 1.0 / (1 << temp);
#ifdef DEBUG
fprintf(stderr, "DEBUG: set fractional bits %d\n", temp);
#endif
Outputf("%% PE: set fractional bits %d\n", temp);
break;
case '=' :
s ++;
abscoords = 1;
#ifdef DEBUG
fputs("DEBUG: absolute\n", stderr);
#endif
Outputf("%% PE: absolute\n");
break;
default :
if (*s >= 63)
{
x = decode_number(&s, base_bits, frac_bits);
y = decode_number(&s, base_bits, frac_bits);
#ifdef DEBUG
fprintf(stderr, "DEBUG: coords %.3f %.3f\n", x, y);
#endif
Outputf("%% PE: coords %.3f %.3f\n", x, y);
if (abscoords)
{
tx = Transform[0][0] * x + Transform[0][1] * y +
Transform[0][2];
ty = Transform[1][0] * x + Transform[1][1] * y +
Transform[1][2];
}
else if (x == 0.0 && y == 0.0)
{
draw = 1;
continue;
}
else
{
tx = Transform[0][0] * x + Transform[0][1] * y +
PenPosition[0];
ty = Transform[1][0] * x + Transform[1][1] * y +
PenPosition[1];
}
if (draw)
{
if (fabs(PenPosition[0] - tx) > 0.001 ||
fabs(PenPosition[1] - ty) > 0.001)
Outputf("%.3f %.3f LI\n", tx, ty);
}
else
Outputf("%.3f %.3f MO\n", tx, ty);
PenPosition[0] = (float)tx;
PenPosition[1] = (float)ty;
draw = 1;
abscoords = 0;
}
else
{
if (*s != '\n' && *s != '\r')
fprintf(stderr, "WARNING: ignoring illegal PE char \'%c\'...\n", *s);
s ++;
}
break;
}
if (!PolygonMode)
Outputf("ST\n");
}
void
PR_plot_relative(int num_params,
param_t *params)
{
PenMotion = 1;
if (num_params > 1)
plot_points(num_params, params);
}
void
PU_pen_up(int num_params,
param_t *params)
{
PenDown = 0;
if (num_params > 1)
plot_points(num_params, params);
}
void
RT_arc_relative3(int num_params,
param_t *params)
{
if (num_params < 4)
return;
if (PenDown)
{
if (!PolygonMode)
Outputf("MP\n");
PenValid = 1;
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
PenPosition[0] = Transform[0][0] * params[0].value.number +
Transform[0][1] * params[1].value.number +
PenPosition[0];
PenPosition[1] = Transform[1][0] * params[0].value.number +
Transform[1][1] * params[1].value.number +
PenPosition[1];
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
}
PenPosition[0] = Transform[0][0] * params[2].value.number +
Transform[0][1] * params[3].value.number +
PenPosition[0];
PenPosition[1] = Transform[1][0] * params[2].value.number +
Transform[1][1] * params[3].value.number +
PenPosition[1];
if (PenDown)
{
Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
if (!PolygonMode)
Outputf("ST\n");
}
}
static double
decode_number(unsigned char **s,
int base_bits,
double frac_bits)
{
double temp,
shift;
int sign;
sign = 0;
if (base_bits == 5)
{
for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
if (**s >= 95 && **s < 127)
{
if (sign == 0)
{
if ((**s - 95) & 1)
sign = -1;
else
sign = 1;
temp += ((**s - 95) & ~1) * shift;
}
else
temp += (**s - 95) * shift;
break;
}
else if (**s < 63)
{
if (**s != '\r' && **s != '\n')
fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
continue;
}
else
{
if (sign == 0)
{
if ((**s - 63) & 1)
sign = -1;
else
sign = 1;
temp += ((**s - 63) & ~1) * shift;
}
else
temp += (**s - 63) * shift;
shift *= 32.0;
}
}
else
{
for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
if (**s >= 191 && **s < 255)
{
if (sign == 0)
{
if ((**s - 191) & 1)
sign = -1;
else
sign = 1;
temp += ((**s - 191) & ~1) * shift;
}
else
temp += (**s - 191) * shift;
break;
}
else if (**s < 63)
{
if (**s != '\r' && **s != '\n')
fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
continue;
}
else
{
if (sign == 0)
{
if ((**s - 63) & 1)
sign = -1;
else
sign = 1;
temp += ((**s - 63) & ~1) * shift;
}
else
temp += (**s - 63) * shift;
shift *= 64.0;
}
}
(*s) ++;
return (temp * sign);
}
static void
plot_points(int num_params,
param_t *params)
{
int i;
float x, y;
if (PenDown)
{
if (!PolygonMode)
{
Outputf("MP\n");
Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
PenValid = 1;
}
}
for (i = 0; i < num_params; i += 2)
{
if (PenMotion == 0)
{
x = Transform[0][0] * params[i + 0].value.number +
Transform[0][1] * params[i + 1].value.number +
Transform[0][2];
y = Transform[1][0] * params[i + 0].value.number +
Transform[1][1] * params[i + 1].value.number +
Transform[1][2];
}
else
{
x = Transform[0][0] * params[i + 0].value.number +
Transform[0][1] * params[i + 1].value.number +
PenPosition[0];
y = Transform[1][0] * params[i + 0].value.number +
Transform[1][1] * params[i + 1].value.number +
PenPosition[1];
}
if (PenDown)
{
if (PolygonMode && i == 0)
Outputf("%.3f %.3f MO\n", x, y);
else if (fabs(PenPosition[0] - x) > 0.001 ||
fabs(PenPosition[1] - y) > 0.001)
Outputf("%.3f %.3f LI\n", x, y);
}
PenPosition[0] = x;
PenPosition[1] = y;
}
if (PenDown)
{
if (!PolygonMode)
Outputf("ST\n");
}
}