]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/hpgl-vector.c
Remove svn:keywords since they cause svn_load_dirs.pl to complain about every file.
[thirdparty/cups.git] / filter / hpgl-vector.c
CommitLineData
ef416fc2 1/*
c07d5b2d 2 * "$Id: hpgl-vector.c 177 2006-06-21 00:20:03Z jlovell $"
ef416fc2 3 *
4 * HP-GL/2 vector routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2005 by Easy Software Products.
7 *
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
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
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.
40 */
41
42/*
43 * Include necessary headers...
44 */
45
46#include "hpgltops.h"
47
48
49/*
50 * Local functions...
51 */
52
53static double decode_number(unsigned char **, int, double);
54static void plot_points(int, param_t *);
55
56
57/*
58 * 'AA_arc_absolute()' - Draw an arc.
59 */
60
61void
62AA_arc_absolute(int num_params, /* I - Number of parameters */
63 param_t *params) /* I - Parameters */
64{
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 */
71
72
73 if (num_params < 3)
74 return;
75
76 x = Transform[0][0] * params[0].value.number +
77 Transform[0][1] * params[1].value.number +
78 Transform[0][2];
79 y = Transform[1][0] * params[0].value.number +
80 Transform[1][1] * params[1].value.number +
81 Transform[1][2];
82
83 dx = PenPosition[0] - x;
84 dy = PenPosition[1] - y;
85
86 start = (float)(180.0 * atan2(dy, dx) / M_PI);
87 if (start < 0.0)
88 start += 360.0f;
89
90 end = start + params[2].value.number;
91 radius = (float)hypot(dx, dy);
92
93 if (PenDown)
94 {
95 if (num_params > 3 && params[3].value.number > 0.0)
96 dt = (float)fabs(params[3].value.number);
97 else
98 dt = 5.0;
99
100 if (!PolygonMode)
101 Outputf("MP\n");
102
103 PenValid = 1;
104
105 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
106
107 if (start < end)
108 for (theta = start + dt; theta < end; theta += dt)
109 {
110 PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
111 PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
112
113 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
114 }
115 else
116 for (theta = start - dt; theta > end; theta -= dt)
117 {
118 PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
119 PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
120
121 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
122 }
123 }
124
125 PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
126 PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
127
128 if (PenDown)
129 {
130 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
131
132 if (!PolygonMode)
133 Outputf("ST\n");
134 }
135}
136
137
138/*
139 * 'AR_arc_relative()' - Draw an arc relative to the current pen
140 * position.
141 */
142
143void
144AR_arc_relative(int num_params, /* I - Number of parameters */
145 param_t *params) /* I - Parameters */
146{
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 */
153
154
155 if (num_params < 3)
156 return;
157
158 x = Transform[0][0] * params[0].value.number +
159 Transform[0][1] * params[1].value.number +
160 PenPosition[0];
161 y = Transform[1][0] * params[0].value.number +
162 Transform[1][1] * params[1].value.number +
163 PenPosition[1];
164
165 dx = PenPosition[0] - x;
166 dy = PenPosition[1] - y;
167
168 start = (float)(180.0 * atan2(dy, dx) / M_PI);
169 if (start < 0.0)
170 start += 360.0f;
171
172 end = start + params[2].value.number;
173 radius = (float)hypot(dx, dy);
174
175 if (PenDown)
176 {
177 if (num_params > 3 && params[3].value.number > 0.0)
178 dt = (float)fabs(params[3].value.number);
179 else
180 dt = 5.0;
181
182 if (!PolygonMode)
183 Outputf("MP\n");
184
185 PenValid = 1;
186
187 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
188
189 if (start < end)
190 for (theta = start + dt; theta < end; theta += dt)
191 {
192 PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
193 PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
194
195 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
196 }
197 else
198 for (theta = start - dt; theta > end; theta -= dt)
199 {
200 PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
201 PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
202
203 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
204 }
205 }
206
207 PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
208 PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
209
210 if (PenDown)
211 {
212 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
213
214 if (!PolygonMode)
215 Outputf("ST\n");
216 }
217}
218
219
220/*
221 * 'AT_arc_absolute3()' - Draw an arc using 3 points.
222 *
223 * Note:
224 *
225 * Currently this only draws two line segments through the
226 * specified points.
227 */
228
229void
230AT_arc_absolute3(int num_params, /* I - Number of parameters */
231 param_t *params) /* I - Parameters */
232{
233 if (num_params < 4)
234 return;
235
236 if (PenDown)
237 {
238 if (!PolygonMode)
239 Outputf("MP\n");
240
241 PenValid = 1;
242
243 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
244
245 PenPosition[0] = Transform[0][0] * params[0].value.number +
246 Transform[0][1] * params[1].value.number +
247 Transform[0][2];
248 PenPosition[1] = Transform[1][0] * params[0].value.number +
249 Transform[1][1] * params[1].value.number +
250 Transform[1][2];
251
252 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
253 }
254
255 PenPosition[0] = Transform[0][0] * params[2].value.number +
256 Transform[0][1] * params[3].value.number +
257 Transform[0][2];
258 PenPosition[1] = Transform[1][0] * params[2].value.number +
259 Transform[1][1] * params[3].value.number +
260 Transform[1][2];
261
262 if (PenDown)
263 {
264 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
265
266 if (!PolygonMode)
267 Outputf("ST\n");
268 }
269}
270
271
272/*
273 * 'CI_circle()' - Draw a circle.
274 */
275
276void
277CI_circle(int num_params, /* I - Number of parameters */
278 param_t *params) /* I - Parameters */
279{
280 float x, y; /* Transformed coordinates */
281 float theta, /* Current angle */
282 dt, /* Step between points */
283 radius; /* Radius of circle */
284
285
286 if (num_params < 1)
287 return;
288
289 if (!PenDown)
290 return;
291
292 radius = params[0].value.number;
293
294 if (num_params > 1)
295 dt = (float)fabs(params[1].value.number);
296 else
297 dt = 5.0;
298
299 if (!PolygonMode)
300 Outputf("MP\n");
301
302 PenValid = 1;
303
304 for (theta = 0.0; theta < 360.0; theta += dt)
305 {
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]);
312
313 Outputf("%.3f %.3f %s\n", x, y, theta == 0.0 ? "MO" : "LI");
314 }
315
316 Outputf("CP\n");
317 if (!PolygonMode)
318 Outputf("ST\n");
319}
320
321
322/*
323 * 'PA_plot_absolute()' - Plot a line using absolute coordinates.
324 */
325
326void
327PA_plot_absolute(int num_params, /* I - Number of parameters */
328 param_t *params) /* I - Parameters */
329{
330 PenMotion = 0;
331
332 if (num_params > 1)
333 plot_points(num_params, params);
334}
335
336
337/*
338 * 'PD_pen_down()' - Start drawing.
339 */
340
341void
342PD_pen_down(int num_params, /* I - Number of parameters */
343 param_t *params) /* I - Parameters */
344{
345 PenDown = 1;
346
347 if (num_params > 1)
348 plot_points(num_params, params);
349}
350
351
352/*
353 * 'PE_polygon_encoded()' - Draw an encoded polyline.
354 */
355
356void
357PE_polyline_encoded(int num_params, /* I - Number of parameters */
358 param_t *params) /* I - Parameters */
359{
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 */
368
369
370 base_bits = 6;
371 frac_bits = 1.0;
372 draw = PenDown;
373 abscoords = 0;
374
375 if (num_params == 0)
376 return;
377
378 if (!PolygonMode)
379 {
380 Outputf("MP\n");
381 PenValid = 0;
382 }
383
384 if (!PenValid)
385 {
386 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
387 PenValid = 1;
388 }
389
390 for (s = (unsigned char *)params[0].value.string; *s != '\0';)
391 switch (*s)
392 {
393 case '7' :
394 s ++;
395 base_bits = 5;
396
397#ifdef DEBUG
398 fputs("DEBUG: 7-bit\n", stderr);
399#endif /* DEBUG */
400
401 Outputf("%% PE: 7-bit\n");
402 break;
403 case ':' : /* Select pen */
404 s ++;
405 PenNumber = (int)decode_number(&s, base_bits, 1.0);
406
407#ifdef DEBUG
408 fprintf(stderr, "DEBUG: set pen #%d\n", PenNumber);
409#endif /* DEBUG */
410
411 Outputf("%% PE: set pen #%d\n", PenNumber);
412
413 if (PageDirty)
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);
417 break;
418 case '<' : /* Next coords are a move-to */
419 draw = 0;
420 s ++;
421
422#ifdef DEBUG
423 fputs("DEBUG: moveto\n", stderr);
424#endif /* DEBUG */
425
426 Outputf("%% PE: moveto\n");
427 break;
428 case '>' : /* Set fractional bits */
429 s ++;
430 temp = (int)decode_number(&s, base_bits, 1.0);
431 frac_bits = 1.0 / (1 << temp);
432
433#ifdef DEBUG
434 fprintf(stderr, "DEBUG: set fractional bits %d\n", temp);
435#endif /* DEBUG */
436
437 Outputf("%% PE: set fractional bits %d\n", temp);
438 break;
439 case '=' : /* Next coords are absolute */
440 s ++;
441 abscoords = 1;
442
443#ifdef DEBUG
444 fputs("DEBUG: absolute\n", stderr);
445#endif /* DEBUG */
446
447 Outputf("%% PE: absolute\n");
448 break;
449 default :
450 if (*s >= 63)
451 {
452 /*
453 * Coordinate...
454 */
455
456 x = decode_number(&s, base_bits, frac_bits);
457 y = decode_number(&s, base_bits, frac_bits);
458
459#ifdef DEBUG
460 fprintf(stderr, "DEBUG: coords %.3f %.3f\n", x, y);
461#endif /* DEBUG */
462
463 Outputf("%% PE: coords %.3f %.3f\n", x, y);
464
465 if (abscoords)
466 {
467 tx = Transform[0][0] * x + Transform[0][1] * y +
468 Transform[0][2];
469 ty = Transform[1][0] * x + Transform[1][1] * y +
470 Transform[1][2];
471 }
472 else if (x == 0.0 && y == 0.0)
473 {
474 draw = 1;
475 continue;
476 }
477 else
478 {
479 tx = Transform[0][0] * x + Transform[0][1] * y +
480 PenPosition[0];
481 ty = Transform[1][0] * x + Transform[1][1] * y +
482 PenPosition[1];
483 }
484
485 if (draw)
486 {
487 if (fabs(PenPosition[0] - tx) > 0.001 ||
488 fabs(PenPosition[1] - ty) > 0.001)
489 Outputf("%.3f %.3f LI\n", tx, ty);
490 }
491 else
492 Outputf("%.3f %.3f MO\n", tx, ty);
493
494 PenPosition[0] = (float)tx;
495 PenPosition[1] = (float)ty;
496
497 draw = 1;
498 abscoords = 0;
499 }
500 else
501 {
502 /*
503 * Junk - ignore...
504 */
505
506 if (*s != '\n' && *s != '\r')
507 fprintf(stderr, "WARNING: ignoring illegal PE char \'%c\'...\n", *s);
508 s ++;
509 }
510 break;
511 }
512
513 if (!PolygonMode)
514 Outputf("ST\n");
515}
516
517
518/*
519 * 'PR_plot_relative()' - Plot a line using relative coordinates.
520 */
521
522void
523PR_plot_relative(int num_params, /* I - Number of parameters */
524 param_t *params) /* I - Parameters */
525{
526 PenMotion = 1;
527
528 if (num_params > 1)
529 plot_points(num_params, params);
530}
531
532
533/*
534 * 'PU_pen_up()' - Stop drawing.
535 */
536
537void
538PU_pen_up(int num_params, /* I - Number of parameters */
539 param_t *params) /* I - Parameters */
540{
541 PenDown = 0;
542
543 if (num_params > 1)
544 plot_points(num_params, params);
545}
546
547
548/*
549 * 'RT_arc_relative3()' - Draw an arc through 3 points relative to the
550 * current pen position.
551 *
552 * Note:
553 *
554 * This currently only draws two line segments through the specified
555 * points.
556 */
557
558void
559RT_arc_relative3(int num_params, /* I - Number of parameters */
560 param_t *params) /* I - Parameters */
561{
562 if (num_params < 4)
563 return;
564
565 if (PenDown)
566 {
567 if (!PolygonMode)
568 Outputf("MP\n");
569
570 PenValid = 1;
571
572 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
573
574 PenPosition[0] = Transform[0][0] * params[0].value.number +
575 Transform[0][1] * params[1].value.number +
576 PenPosition[0];
577 PenPosition[1] = Transform[1][0] * params[0].value.number +
578 Transform[1][1] * params[1].value.number +
579 PenPosition[1];
580
581 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
582 }
583
584 PenPosition[0] = Transform[0][0] * params[2].value.number +
585 Transform[0][1] * params[3].value.number +
586 PenPosition[0];
587 PenPosition[1] = Transform[1][0] * params[2].value.number +
588 Transform[1][1] * params[3].value.number +
589 PenPosition[1];
590
591 if (PenDown)
592 {
593 Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
594
595 if (!PolygonMode)
596 Outputf("ST\n");
597 }
598}
599
600
601/*
602 * 'decode_number()' - Decode an encoded number.
603 */
604
605static double /* O - Value */
606decode_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 */
609{
610 double temp, /* Current value */
611 shift; /* Multiplier */
612 int sign; /* Sign of result */
613
614
615 sign = 0;
616
617 if (base_bits == 5)
618 {
619 for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
620 if (**s >= 95 && **s < 127)
621 {
622 if (sign == 0)
623 {
624 if ((**s - 95) & 1)
625 sign = -1;
626 else
627 sign = 1;
628
629 temp += ((**s - 95) & ~1) * shift;
630 }
631 else
632 temp += (**s - 95) * shift;
633 break;
634 }
635 else if (**s < 63)
636 {
637 if (**s != '\r' && **s != '\n')
638 fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
639
640 continue;
641 }
642 else
643 {
644 if (sign == 0)
645 {
646 if ((**s - 63) & 1)
647 sign = -1;
648 else
649 sign = 1;
650
651 temp += ((**s - 63) & ~1) * shift;
652 }
653 else
654 temp += (**s - 63) * shift;
655
656 shift *= 32.0;
657 }
658 }
659 else
660 {
661 for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
662 if (**s >= 191 && **s < 255)
663 {
664 if (sign == 0)
665 {
666 if ((**s - 191) & 1)
667 sign = -1;
668 else
669 sign = 1;
670
671 temp += ((**s - 191) & ~1) * shift;
672 }
673 else
674 temp += (**s - 191) * shift;
675 break;
676 }
677 else if (**s < 63)
678 {
679 if (**s != '\r' && **s != '\n')
680 fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
681
682 continue;
683 }
684 else
685 {
686 if (sign == 0)
687 {
688 if ((**s - 63) & 1)
689 sign = -1;
690 else
691 sign = 1;
692
693 temp += ((**s - 63) & ~1) * shift;
694 }
695 else
696 temp += (**s - 63) * shift;
697
698 shift *= 64.0;
699 }
700 }
701
702 (*s) ++;
703
704 return (temp * sign);
705}
706
707
708/*
709 * 'plot_points()' - Plot the specified points.
710 */
711
712static void
713plot_points(int num_params, /* I - Number of parameters */
714 param_t *params) /* I - Parameters */
715{
716 int i; /* Looping var */
717 float x, y; /* Transformed coordinates */
718
719
720 if (PenDown)
721 {
722 if (!PolygonMode)
723 {
724 Outputf("MP\n");
725 Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
726
727 PenValid = 1;
728 }
729 }
730
731 for (i = 0; i < num_params; i += 2)
732 {
733 if (PenMotion == 0)
734 {
735 x = Transform[0][0] * params[i + 0].value.number +
736 Transform[0][1] * params[i + 1].value.number +
737 Transform[0][2];
738 y = Transform[1][0] * params[i + 0].value.number +
739 Transform[1][1] * params[i + 1].value.number +
740 Transform[1][2];
741 }
742 else
743 {
744 x = Transform[0][0] * params[i + 0].value.number +
745 Transform[0][1] * params[i + 1].value.number +
746 PenPosition[0];
747 y = Transform[1][0] * params[i + 0].value.number +
748 Transform[1][1] * params[i + 1].value.number +
749 PenPosition[1];
750 }
751
752 if (PenDown)
753 {
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);
759 }
760
761 PenPosition[0] = x;
762 PenPosition[1] = y;
763 }
764
765 if (PenDown)
766 {
767 if (!PolygonMode)
768 Outputf("ST\n");
769 }
770}
771
772
773/*
c07d5b2d 774 * End of "$Id: hpgl-vector.c 177 2006-06-21 00:20:03Z jlovell $".
ef416fc2 775 */