]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/hpgl-vector.c
809290a0ec9dcf2d964315ee2e3e43afadbc86c1
4 * HP-GL/2 vector routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2005 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * AA_arc_absolute() - Draw an arc.
29 * AR_arc_relative() - Draw an arc relative to the current pen
30 * AT_arc_absolute3() - Draw an arc using 3 points.
31 * CI_circle() - Draw a circle.
32 * PA_plot_absolute() - Plot a line using absolute coordinates.
33 * PD_pen_down() - Start drawing.
34 * PE_polygon_encoded() - Draw an encoded polyline.
35 * PR_plot_relative() - Plot a line using relative coordinates.
36 * PU_pen_up() - Stop drawing.
37 * RT_arc_relative3() - Draw an arc through 3 points relative to the
38 * decode_number() - Decode an encoded number.
39 * plot_points() - Plot the specified points.
43 * Include necessary headers...
53 static double decode_number(unsigned char **, int, double);
54 static void plot_points(int, param_t
*);
58 * 'AA_arc_absolute()' - Draw an arc.
62 AA_arc_absolute(int num_params
, /* I - Number of parameters */
63 param_t
*params
) /* I - Parameters */
65 float x
, y
, /* Transformed coordinates */
66 dx
, dy
; /* Distance from current pen */
67 float start
, end
, /* Start and end angles */
68 theta
, /* Current angle */
69 dt
, /* Step between points */
70 radius
; /* Radius of arc */
76 x
= Transform
[0][0] * params
[0].value
.number
+
77 Transform
[0][1] * params
[1].value
.number
+
79 y
= Transform
[1][0] * params
[0].value
.number
+
80 Transform
[1][1] * params
[1].value
.number
+
83 dx
= PenPosition
[0] - x
;
84 dy
= PenPosition
[1] - y
;
86 start
= (float)(180.0 * atan2(dy
, dx
) / M_PI
);
90 end
= start
+ params
[2].value
.number
;
91 radius
= (float)hypot(dx
, dy
);
95 if (num_params
> 3 && params
[3].value
.number
> 0.0)
96 dt
= (float)fabs(params
[3].value
.number
);
105 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
108 for (theta
= start
+ dt
; theta
< end
; theta
+= dt
)
110 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* theta
/ 180.0));
111 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* theta
/ 180.0));
113 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
116 for (theta
= start
- dt
; theta
> end
; theta
-= dt
)
118 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* theta
/ 180.0));
119 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* theta
/ 180.0));
121 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
125 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* end
/ 180.0));
126 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* end
/ 180.0));
130 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
139 * 'AR_arc_relative()' - Draw an arc relative to the current pen
144 AR_arc_relative(int num_params
, /* I - Number of parameters */
145 param_t
*params
) /* I - Parameters */
147 float x
, y
, /* Transformed coordinates */
148 dx
, dy
; /* Distance from current pen */
149 float start
, end
, /* Start and end angles */
150 theta
, /* Current angle */
151 dt
, /* Step between points */
152 radius
; /* Radius of arc */
158 x
= Transform
[0][0] * params
[0].value
.number
+
159 Transform
[0][1] * params
[1].value
.number
+
161 y
= Transform
[1][0] * params
[0].value
.number
+
162 Transform
[1][1] * params
[1].value
.number
+
165 dx
= PenPosition
[0] - x
;
166 dy
= PenPosition
[1] - y
;
168 start
= (float)(180.0 * atan2(dy
, dx
) / M_PI
);
172 end
= start
+ params
[2].value
.number
;
173 radius
= (float)hypot(dx
, dy
);
177 if (num_params
> 3 && params
[3].value
.number
> 0.0)
178 dt
= (float)fabs(params
[3].value
.number
);
187 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
190 for (theta
= start
+ dt
; theta
< end
; theta
+= dt
)
192 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* theta
/ 180.0));
193 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* theta
/ 180.0));
195 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
198 for (theta
= start
- dt
; theta
> end
; theta
-= dt
)
200 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* theta
/ 180.0));
201 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* theta
/ 180.0));
203 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
207 PenPosition
[0] = (float)(x
+ radius
* cos(M_PI
* end
/ 180.0));
208 PenPosition
[1] = (float)(y
+ radius
* sin(M_PI
* end
/ 180.0));
212 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
221 * 'AT_arc_absolute3()' - Draw an arc using 3 points.
225 * Currently this only draws two line segments through the
230 AT_arc_absolute3(int num_params
, /* I - Number of parameters */
231 param_t
*params
) /* I - Parameters */
243 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
245 PenPosition
[0] = Transform
[0][0] * params
[0].value
.number
+
246 Transform
[0][1] * params
[1].value
.number
+
248 PenPosition
[1] = Transform
[1][0] * params
[0].value
.number
+
249 Transform
[1][1] * params
[1].value
.number
+
252 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
255 PenPosition
[0] = Transform
[0][0] * params
[2].value
.number
+
256 Transform
[0][1] * params
[3].value
.number
+
258 PenPosition
[1] = Transform
[1][0] * params
[2].value
.number
+
259 Transform
[1][1] * params
[3].value
.number
+
264 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
273 * 'CI_circle()' - Draw a circle.
277 CI_circle(int num_params
, /* I - Number of parameters */
278 param_t
*params
) /* I - Parameters */
280 float x
, y
; /* Transformed coordinates */
281 float theta
, /* Current angle */
282 dt
, /* Step between points */
283 radius
; /* Radius of circle */
292 radius
= params
[0].value
.number
;
295 dt
= (float)fabs(params
[1].value
.number
);
304 for (theta
= 0.0; theta
< 360.0; theta
+= dt
)
306 x
= (float)(PenPosition
[0] +
307 radius
* cos(M_PI
* theta
/ 180.0) * Transform
[0][0] +
308 radius
* sin(M_PI
* theta
/ 180.0) * Transform
[0][1]);
309 y
= (float)(PenPosition
[1] +
310 radius
* cos(M_PI
* theta
/ 180.0) * Transform
[1][0] +
311 radius
* sin(M_PI
* theta
/ 180.0) * Transform
[1][1]);
313 Outputf("%.3f %.3f %s\n", x
, y
, theta
== 0.0 ? "MO" : "LI");
323 * 'PA_plot_absolute()' - Plot a line using absolute coordinates.
327 PA_plot_absolute(int num_params
, /* I - Number of parameters */
328 param_t
*params
) /* I - Parameters */
333 plot_points(num_params
, params
);
338 * 'PD_pen_down()' - Start drawing.
342 PD_pen_down(int num_params
, /* I - Number of parameters */
343 param_t
*params
) /* I - Parameters */
348 plot_points(num_params
, params
);
353 * 'PE_polygon_encoded()' - Draw an encoded polyline.
357 PE_polyline_encoded(int num_params
, /* I - Number of parameters */
358 param_t
*params
) /* I - Parameters */
360 unsigned char *s
; /* Pointer into string */
361 int temp
, /* Temporary value */
362 base_bits
, /* Data bits per byte */
363 draw
, /* Draw or move */
364 abscoords
; /* Use absolute coordinates */
365 double tx
, ty
, /* Transformed coordinates */
366 x
, y
, /* Raw coordinates */
367 frac_bits
; /* Multiplier for encoded number */
386 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
390 for (s
= (unsigned char *)params
[0].value
.string
; *s
!= '\0';)
398 fputs("DEBUG: 7-bit\n", stderr
);
401 Outputf("%% PE: 7-bit\n");
403 case ':' : /* Select pen */
405 PenNumber
= (int)decode_number(&s
, base_bits
, 1.0);
408 fprintf(stderr
, "DEBUG: set pen #%d\n", PenNumber
);
411 Outputf("%% PE: set pen #%d\n", PenNumber
);
414 printf("%.3f %.3f %.3f %.2f SP\n", Pens
[PenNumber
].rgb
[0],
415 Pens
[PenNumber
].rgb
[1], Pens
[PenNumber
].rgb
[2],
416 Pens
[PenNumber
].width
* PenScaling
);
418 case '<' : /* Next coords are a move-to */
423 fputs("DEBUG: moveto\n", stderr
);
426 Outputf("%% PE: moveto\n");
428 case '>' : /* Set fractional bits */
430 temp
= (int)decode_number(&s
, base_bits
, 1.0);
431 frac_bits
= 1.0 / (1 << temp
);
434 fprintf(stderr
, "DEBUG: set fractional bits %d\n", temp
);
437 Outputf("%% PE: set fractional bits %d\n", temp
);
439 case '=' : /* Next coords are absolute */
444 fputs("DEBUG: absolute\n", stderr
);
447 Outputf("%% PE: absolute\n");
456 x
= decode_number(&s
, base_bits
, frac_bits
);
457 y
= decode_number(&s
, base_bits
, frac_bits
);
460 fprintf(stderr
, "DEBUG: coords %.3f %.3f\n", x
, y
);
463 Outputf("%% PE: coords %.3f %.3f\n", x
, y
);
467 tx
= Transform
[0][0] * x
+ Transform
[0][1] * y
+
469 ty
= Transform
[1][0] * x
+ Transform
[1][1] * y
+
472 else if (x
== 0.0 && y
== 0.0)
479 tx
= Transform
[0][0] * x
+ Transform
[0][1] * y
+
481 ty
= Transform
[1][0] * x
+ Transform
[1][1] * y
+
487 if (fabs(PenPosition
[0] - tx
) > 0.001 ||
488 fabs(PenPosition
[1] - ty
) > 0.001)
489 Outputf("%.3f %.3f LI\n", tx
, ty
);
492 Outputf("%.3f %.3f MO\n", tx
, ty
);
494 PenPosition
[0] = (float)tx
;
495 PenPosition
[1] = (float)ty
;
506 if (*s
!= '\n' && *s
!= '\r')
507 fprintf(stderr
, "WARNING: ignoring illegal PE char \'%c\'...\n", *s
);
519 * 'PR_plot_relative()' - Plot a line using relative coordinates.
523 PR_plot_relative(int num_params
, /* I - Number of parameters */
524 param_t
*params
) /* I - Parameters */
529 plot_points(num_params
, params
);
534 * 'PU_pen_up()' - Stop drawing.
538 PU_pen_up(int num_params
, /* I - Number of parameters */
539 param_t
*params
) /* I - Parameters */
544 plot_points(num_params
, params
);
549 * 'RT_arc_relative3()' - Draw an arc through 3 points relative to the
550 * current pen position.
554 * This currently only draws two line segments through the specified
559 RT_arc_relative3(int num_params
, /* I - Number of parameters */
560 param_t
*params
) /* I - Parameters */
572 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
574 PenPosition
[0] = Transform
[0][0] * params
[0].value
.number
+
575 Transform
[0][1] * params
[1].value
.number
+
577 PenPosition
[1] = Transform
[1][0] * params
[0].value
.number
+
578 Transform
[1][1] * params
[1].value
.number
+
581 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
584 PenPosition
[0] = Transform
[0][0] * params
[2].value
.number
+
585 Transform
[0][1] * params
[3].value
.number
+
587 PenPosition
[1] = Transform
[1][0] * params
[2].value
.number
+
588 Transform
[1][1] * params
[3].value
.number
+
593 Outputf("%.3f %.3f LI\n", PenPosition
[0], PenPosition
[1]);
602 * 'decode_number()' - Decode an encoded number.
605 static double /* O - Value */
606 decode_number(unsigned char **s
, /* IO - String to decode */
607 int base_bits
, /* I - Number of data bits per byte */
608 double frac_bits
) /* I - Multiplier for fractional data */
610 double temp
, /* Current value */
611 shift
; /* Multiplier */
612 int sign
; /* Sign of result */
619 for (temp
= 0.0, shift
= frac_bits
* 0.5; **s
!= '\0'; (*s
) ++)
620 if (**s
>= 95 && **s
< 127)
629 temp
+= ((**s
- 95) & ~1) * shift
;
632 temp
+= (**s
- 95) * shift
;
637 if (**s
!= '\r' && **s
!= '\n')
638 fprintf(stderr
, "ERROR: Bad PE character 0x%02X!\n", **s
);
651 temp
+= ((**s
- 63) & ~1) * shift
;
654 temp
+= (**s
- 63) * shift
;
661 for (temp
= 0.0, shift
= frac_bits
* 0.5; **s
!= '\0'; (*s
) ++)
662 if (**s
>= 191 && **s
< 255)
671 temp
+= ((**s
- 191) & ~1) * shift
;
674 temp
+= (**s
- 191) * shift
;
679 if (**s
!= '\r' && **s
!= '\n')
680 fprintf(stderr
, "ERROR: Bad PE character 0x%02X!\n", **s
);
693 temp
+= ((**s
- 63) & ~1) * shift
;
696 temp
+= (**s
- 63) * shift
;
704 return (temp
* sign
);
709 * 'plot_points()' - Plot the specified points.
713 plot_points(int num_params
, /* I - Number of parameters */
714 param_t
*params
) /* I - Parameters */
716 int i
; /* Looping var */
717 float x
, y
; /* Transformed coordinates */
725 Outputf("%.3f %.3f MO\n", PenPosition
[0], PenPosition
[1]);
731 for (i
= 0; i
< num_params
; i
+= 2)
735 x
= Transform
[0][0] * params
[i
+ 0].value
.number
+
736 Transform
[0][1] * params
[i
+ 1].value
.number
+
738 y
= Transform
[1][0] * params
[i
+ 0].value
.number
+
739 Transform
[1][1] * params
[i
+ 1].value
.number
+
744 x
= Transform
[0][0] * params
[i
+ 0].value
.number
+
745 Transform
[0][1] * params
[i
+ 1].value
.number
+
747 y
= Transform
[1][0] * params
[i
+ 0].value
.number
+
748 Transform
[1][1] * params
[i
+ 1].value
.number
+
754 if (PolygonMode
&& i
== 0)
755 Outputf("%.3f %.3f MO\n", x
, y
);
756 else if (fabs(PenPosition
[0] - x
) > 0.001 ||
757 fabs(PenPosition
[1] - y
) > 0.001)
758 Outputf("%.3f %.3f LI\n", x
, y
);