1 /*
2 Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved.
3 Distributed by Free Software Foundation, Inc.
4
5 This file is part of HP2xx.
6
7 HP2xx is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
9 to anyone for the consequences of using it or for whether it serves any
10 particular purpose or works at all, unless he says so in writing. Refer
11 to the GNU General Public License, Version 2 or later, for full details.
12
13 Everyone is granted permission to copy, modify and redistribute
14 HP2xx, but only under the conditions described in the GNU General Public
15 License. A copy of this license is supposed to have been
16 given to you along with HP2xx so you can know your rights and
17 responsibilities. It should be in a file named COPYING. Among other
18 things, the copyright notice and this notice must be preserved on all
19 copies.
20
21 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 */
23
24 /** picbuf.c: Part of hp2xx project dealing with the picture buffer
25 **
26 ** 91/01/19 V 1.00 HWW Derived from hptopcl.c
27 ** 91/01/29 V 1.01 HWW Tested on SUN
28 ** 91/02/15 V 1.02 HWW stdlib.h supported
29 ** 91/02/20 V 1.03a HWW minor mod. in fread(); adaptation to
30 ** new HPGL_Pt structures in tmpfile_to_PicBuf()
31 ** 91/06/09 V 1.04 HWW new options acknowledged; minimal changes
32 ** 91/10/15 V 1.05 HWW ANSI_C
33 ** 91/11/20 V 1.06 HWW "SPn;" consequences
34 ** 92/02/17 V 1.07b HWW Preparations for font support
35 ** 92/05/24 V 2.00c HWW Color supported! Fonts ok now; "init" bug fixed
36 ** 92/06/08 V 2.00d HWW GIVE_BACK: 5 --> 8; free_PicBuf() debugged
37 ** 92/12/24 V 2.00e HWW plot_RowBuf() augmented to bit REsetting
38 ** 93/04/02 V 2.01a HWW Always use four bit planes in color mode!
39 ** Out-dated "DotBlock" concept replaced by "char".
40 ** 94/02/14 V 2.10 HWW New parameter structs; restructured
41 ** Improved cleanup & error handling
42 ** 00/07/16 MK Modify pensize correction in size_Pixbuf
43 ** for new .1 pixel pensize unit scheme (G.B.)
44 **/
45
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #ifndef _NO_VCL
50 #include <unistd.h>
51 #endif
52 #include <string.h>
53 #include <math.h>
54 #include "bresnham.h"
55 #include "murphy.h"
56 #include "pendef.h"
57 #include "lindef.h"
58 #include "picbuf.h"
59 #include "hp2xx.h"
60 #include "hpgl.h"
61
62
63 static RowBuf *first_buf = NULL, *last_buf = NULL;
64
65 static int X_Offset = 0;
66 static int Y_Offset = 0;
67
68 #ifndef SEEK_SET
69 #define SEEK_SET 0
70 #endif
71
72
73
swapout_RowBuf(RowBuf * row,const PicBuf * picbuf)74 static void swapout_RowBuf(RowBuf * row, const PicBuf * picbuf)
75 {
76 if (fseek
77 (picbuf->sd, (long) row->index * picbuf->nb * picbuf->depth,
78 SEEK_SET)) {
79 PError("swapout_RowBuf (on seek)");
80 exit(ERROR);
81 }
82
83 if ((int)
84 fwrite((char *) row->buf, (size_t) picbuf->nb,
85 (size_t) picbuf->depth, picbuf->sd)
86 != picbuf->depth) {
87 PError("swapout_RowBuf (on write)");
88 exit(ERROR);
89 }
90 }
91
92
93
swapin_RowBuf(RowBuf * row,const PicBuf * picbuf)94 static void swapin_RowBuf(RowBuf * row, const PicBuf * picbuf)
95 {
96 if (fseek
97 (picbuf->sd, (long) row->index * picbuf->nb * picbuf->depth,
98 SEEK_SET)) {
99 PError("swapin_RowBuf (on seek)");
100 exit(ERROR);
101 }
102
103 if ((int)
104 fread((char *) row->buf, (size_t) picbuf->nb,
105 (size_t) picbuf->depth, picbuf->sd)
106 != picbuf->depth) {
107 PError("swapin_RowBuf (on read)");
108 exit(ERROR);
109 }
110 }
111
112
113
114
115
link_RowBuf(RowBuf * act,RowBuf * prev)116 static void link_RowBuf(RowBuf * act, RowBuf * prev)
117 {
118 if (prev == NULL) { /* Make act the new "first_buf" */
119 if (first_buf == NULL) {
120 first_buf = act;
121 act->next = act->prev = NULL;
122 return;
123 }
124 act->next = first_buf;
125 act->prev = NULL;
126 first_buf->prev = act;
127 first_buf = act;
128 } else { /* Squeeze act between prev & prev->next */
129
130 if ((act->next = prev->next) != NULL)
131 act->next->prev = act;
132 act->prev = prev;
133 prev->next = act;
134 }
135 }
136
137
138
139
140
unlink_RowBuf(RowBuf * act)141 static void unlink_RowBuf(RowBuf * act)
142 {
143 if ((act->prev == NULL) && (act->next == NULL))
144 return;
145
146 if (act->prev)
147 act->prev->next = act->next;
148 else
149 first_buf = act->next;
150
151 if (act->next)
152 act->next->prev = act->prev;
153 else
154 last_buf = act->prev;
155
156 act->next = act->prev = NULL;
157 }
158
159
160
161
get_RowBuf(const PicBuf * pb,int index)162 RowBuf *get_RowBuf(const PicBuf * pb, int index)
163 {
164 RowBuf *row;
165
166 if (pb == NULL)
167 return NULL;
168 if (index < 0 || index >= pb->nr) {
169 Eprintf("get_RowBuf: Illegal y (%d not in [0, %d])\n",
170 index, pb->nr - 1);
171 return NULL;
172 }
173
174 row = pb->row + index;
175
176 /**
177 ** If swapped, load first. Put into first position, if not already there:
178 **/
179 if ((row->prev == NULL) && (row->next == NULL)) {
180 swapout_RowBuf(last_buf, pb);
181 row->buf = last_buf->buf;
182 unlink_RowBuf(last_buf); /* Mark as swapped */
183 swapin_RowBuf(row, pb);
184 link_RowBuf(row, NULL); /* Put in first position */
185 } else if (row->prev != NULL) {
186 unlink_RowBuf(row);
187 link_RowBuf(row, NULL); /* Put in first position */
188 }
189 /* else: Leave it in first position */
190
191 return row;
192 }
193
194
195
196
197
plot_RowBuf(RowBuf * rowbuf,int x,int depth,PEN_C color_index)198 static void plot_RowBuf(RowBuf * rowbuf, int x, int depth,
199 PEN_C color_index)
200 /**
201 ** Write color index into pixel x of given row buffer
202 **/
203 {
204 int i, Mask;
205 Byte *addr;
206
207 if (rowbuf == NULL)
208 return;
209 /**
210 ** Color_index is either the low bit (b/w) or the low nybble (color)
211 ** rowbuf->buf is either a sequence of such bits or nybbles.
212 ** High bits show left, low bits show right.
213 **
214 ** This is a time-critical step, so code here is compact,
215 ** but not easily readable...
216 **/
217
218 if (depth == 1) {
219 if (color_index > 1)
220 color_index = 1;
221 Mask = 0x80;
222 if ((i = x & 0x07) != 0) {
223 Mask >>= i;
224 if (i != 7)
225 color_index <<= (7 - i);
226 } else
227 color_index <<= 7;
228 addr = rowbuf->buf + (x >> 3);
229 } else if (depth == 4) {
230 Mask = 0xF0;
231 if ((x & 0x01) != 0)
232 Mask >>= 4;
233 else
234 color_index <<= 4;
235 addr = rowbuf->buf + (x >> 1);
236 } else {
237 addr = rowbuf->buf + x;
238 Mask = 0x00;
239 }
240 if (depth < 8) {
241 *addr &= ~Mask;
242 *addr |= color_index;
243 } else
244 *addr = (Byte) color_index;
245 }
246
247
248
249
250
index_from_RowBuf(const RowBuf * rowbuf,int x,const PicBuf * pb)251 int index_from_RowBuf(const RowBuf * rowbuf, int x, const PicBuf * pb)
252 /**
253 ** Return color index of pixel x in given row
254 **/
255 {
256 int i, Mask, color_index;
257 Byte *addr;
258
259 if (pb->depth == 1) {
260 Mask = 0x80;
261 if ((i = x & 0x07) != 0)
262 Mask >>= i;
263 addr = rowbuf->buf + (x >> 3);
264 return (*addr & Mask) ? xxForeground : xxBackground;
265 } else if (pb->depth == 4) {
266 Mask = 0xF0;
267 if ((x & 0x01) != 0)
268 Mask >>= 4;
269 addr = rowbuf->buf + (x >> 1);
270 color_index = *addr & Mask;
271 if ((x & 0x01) == 0)
272 color_index >>= 4;
273 return color_index;
274 } else {
275 addr = rowbuf->buf + x;
276 color_index = *addr;
277 return color_index;
278 }
279 }
280
281
282
283
284
285 static void
HPcoord_to_dotcoord(const HPGL_Pt * HP_P,DevPt * DevP,const OUT_PAR * po)286 HPcoord_to_dotcoord(const HPGL_Pt * HP_P, DevPt * DevP, const OUT_PAR * po)
287 {
288 DevP->x = (int) ((HP_P->x - po->xmin) * po->HP_to_xdots);
289 DevP->y = (int) ((HP_P->y - po->ymin) * po->HP_to_ydots);
290 }
291
292
293
size_PicBuf(const GEN_PAR * pg,const OUT_PAR * po,int * p_rows,int * p_cols)294 void size_PicBuf(const GEN_PAR * pg, const OUT_PAR * po, int *p_rows,
295 int *p_cols)
296 {
297 HPGL_Pt HP_Pt;
298 DevPt D_Pt;
299 int maxps;
300
301 HP_Pt.x = po->xmax;
302 HP_Pt.y = po->ymax;
303 HPcoord_to_dotcoord(&HP_Pt, &D_Pt, po);
304 /* Pensize correction */
305 /* maxps= (int)(1. + pg->maxpensize *po->HP_to_xdots/0.025); */
306 maxps = 1 + ceil(pg->maxpensize * po->HP_to_xdots / 0.025);
307 X_Offset = maxps / 2;
308 Y_Offset = maxps / 2;
309
310 /* printf("maxps = %d\n",maxps);*/
311 *p_cols = D_Pt.x + maxps + 1;
312 *p_rows = D_Pt.y + maxps + 1;
313 }
314
315
allocate_PicBuf(const GEN_PAR * pg,int n_rows,int n_cols)316 PicBuf *allocate_PicBuf(const GEN_PAR * pg, int n_rows, int n_cols)
317 /**
318 ** Here we allocate the picture buffer. This memory is used by all raster
319 ** modes. It is organized in rows (scan lines). Rows which do not
320 ** end on a byte boundary will be right-padded with "background" bits.
321 **
322 ** If colors are active, there will always be "four bit" layers per row,
323 ** even if you need only three colors.
324 ** These layers are implemented by allocating longer rows
325 ** (regular length times number of bit planes per pel (depth)).
326 **
327 ** We try to allocate all row buffers from main memory first.
328 ** If allocation fails, we first free a few lines (see constant GIVE_BACK)
329 ** to avoid operation close to the dyn. memory limit,
330 ** and then initiate swapping to a file.
331 **/
332 {
333 PicBuf *pb;
334 RowBuf *prev, *act;
335 int nr, not_allocated;
336 #define GIVE_BACK 8
337
338 if ((pb = (PicBuf *) malloc(sizeof(*pb))) == NULL) {
339 Eprintf("Cannot malloc() PicBuf structure\n");
340 return NULL;
341 }
342
343 pb->nr = n_rows;
344 pb->nc = n_cols;
345 pb->sd = NULL;
346 pb->sf_name = NULL;
347 pb->row = NULL;
348 first_buf = NULL; /* Re-init for multiple-file */
349 last_buf = NULL; /* applications */
350
351 /**
352 ** Number of buffer bytes per row:
353 **
354 ** Example:
355 **
356 ** dot range (horiz.): 0...2595 ==> 2596 dots per row, pb->nc=2096 ==>
357 ** [2596 bits / 8 bits per byte]
358 ** ==> 324 DotBlocks + 4 bits which require another whole byte (!)
359 **/
360
361 pb->nb = (pb->nc >> 3);
362 if (pb->nc & 7)
363 pb->nb++;
364
365 /**
366 ** Auto-detection of depth (# bits per pel):
367 **
368 ** B/W mode (1 bit per pel, Foreground & Background),
369 ** or color mode (4 bits per pel)
370 **/
371
372 pb->depth = (pg->is_color) ? 4 : 1;
373 if (pg->is_color && pg->maxcolor > 15) {
374 pb->depth = 8;
375 if (!pg->quiet)
376 fprintf(stderr, "using 8bpp picbuf for NP>15\n");
377 }
378 /**
379 ** Allocate a (large) array of RowBuf structures: One for each scan line.
380 ** !!! The NULL initialization done implicitly by calloc() is crucial !!!
381 **/
382
383 if ((pb->row =
384 (RowBuf *) calloc((unsigned) pb->nr, sizeof(RowBuf)))
385 == NULL) {
386 Eprintf("Cannot calloc() %d RowBuf structures\n", pb->nr);
387 free_PicBuf(pb);
388 return NULL;
389 }
390
391 /**
392 ** Now try to allocate as many buffers as possible. Double-link all RowBuf's
393 ** which succeed in buffer allocation, leave the rest isolated (swapping
394 ** candidates!)
395 **/
396
397 not_allocated = 0;
398 prev = (RowBuf *) NULL;
399 for (nr = 0, act = pb->row; nr < pb->nr; nr++, act++) {
400 act->prev = act->next = NULL;
401 act->index = nr;
402 if ((act->buf =
403 (Byte *) calloc((unsigned) (pb->nb * pb->depth),
404 1)) == NULL)
405 not_allocated++;
406 else {
407 link_RowBuf(act, prev);
408 prev = act;
409 last_buf = act;
410 }
411 }
412
413 /**
414 ** Prepare swapping
415 **/
416
417 if (not_allocated) {
418 if (last_buf->index > GIVE_BACK)
419 for (nr = 0; nr < GIVE_BACK; nr++) {
420 /* Return some memory for internal use */
421 free((char *) last_buf->buf);
422 unlink_RowBuf(last_buf);
423 not_allocated++;
424 } else {
425 Eprintf
426 ("\nNot enough memory for swapping -- sorry!\n");
427 free_PicBuf(pb);
428 return NULL;
429 }
430
431 Eprintf("\nCouldn't allocate %d out of %d row buffers.\n",
432 not_allocated, pb->nr);
433 Eprintf("Swapping to disk...\n");
434 pb->sf_name = pg->swapfile;
435 if ((pb->sd = fopen(pb->sf_name, WRITE_BIN)) == NULL) {
436 Eprintf("Couldn't open swap file '%s'\n",
437 pb->sf_name);
438 PError("hp2xx");
439 free_PicBuf(pb);
440 return NULL;
441 }
442
443 /**
444 ** Init. swap file data to background color (0), using a shortcut by
445 ** assuming that all data are stored without gaps. Thus, instead of
446 ** row-by-row operation, we simply write a sufficient number of 0 rows
447 ** into the swap file sequentially.
448 **/
449
450 for (nr = 0; nr < pb->nr; nr++)
451 if ((int)
452 fwrite((char *) pb->row[0].buf,
453 (size_t) pb->nb, (size_t) pb->depth,
454 pb->sd)
455 != pb->depth) {
456 Eprintf("Couldn't clear swap file!\n");
457 PError("hp2xx");
458 free_PicBuf(pb);
459 return NULL;
460 }
461 }
462 return pb;
463 }
464
465
466
467
free_PicBuf(PicBuf * pb)468 void free_PicBuf(PicBuf * pb)
469 /**
470 ** De-allocate all row buffers and the picture puffer struct,
471 ** remove the swap file (if any).
472 **/
473 {
474 RowBuf *row;
475 int i;
476
477 if (pb == NULL)
478 return;
479
480 if (pb->sd) {
481 fclose(pb->sd);
482 pb->sd = NULL;
483 #ifdef VAX
484 delete(pb->sf_name);
485 #else
486 unlink(pb->sf_name);
487 #endif
488 }
489 for (i = 0; i < pb->nr; i++) {
490 row = &(pb->row[i]);
491 if (row != NULL
492 && (row->prev != NULL || row->next != NULL))
493 free((char *) row->buf);
494 }
495 free((char *) pb->row);
496 free((char *) pb);
497 }
498
499
500
501
502
plot_PicBuf(PicBuf * pb,DevPt * pt,PEN_C color_index)503 void plot_PicBuf(PicBuf * pb, DevPt * pt, PEN_C color_index)
504 {
505 if ((pt->x + X_Offset) < 0 || pt->x > (pb->nc - X_Offset)) {
506 Eprintf("plot_PicBuf: Illegal x (%d not in [0, %d])\n",
507 pt->x + X_Offset, pb->nc);
508 return;
509 }
510 plot_RowBuf(get_RowBuf(pb, pt->y + Y_Offset), pt->x + X_Offset,
511 pb->depth, color_index);
512 }
513
514
515
516
index_from_PicBuf(const PicBuf * pb,const DevPt * pt)517 int index_from_PicBuf(const PicBuf * pb, const DevPt * pt)
518 {
519 if (pt->x < 0 || pt->x > pb->nc) {
520 Eprintf
521 ("index_from_PicBuf: Illegal x (%d not in [0, %d])\n",
522 pt->x, pb->nc);
523 return 0;
524 }
525 return index_from_RowBuf(get_RowBuf(pb, pt->y), pt->x, pb);
526 }
527
528
dot_PicBuf(DevPt * p0,int pensize,PEN_C pencolor,PicBuf * pb)529 static void dot_PicBuf(DevPt * p0, int pensize, PEN_C pencolor,
530 PicBuf * pb)
531 {
532
533 DevPt pt;
534
535 int dd = 3 - (pensize);
536 int dx = 0;
537 int dy = pensize / 2;
538
539 for (; dx <= dy; dx++) {
540 for (pt.x = p0->x - dx, pt.y = p0->y + dy;
541 pt.x <= p0->x + dx; pt.x++)
542 plot_PicBuf(pb, &pt, pencolor);
543
544 for (pt.x = p0->x - dx, pt.y = p0->y - dy;
545 pt.x <= p0->x + dx; pt.x++)
546 plot_PicBuf(pb, &pt, pencolor);
547
548 for (pt.x = p0->x - dy, pt.y = p0->y + dx;
549 pt.x <= p0->x + dy; pt.x++)
550 plot_PicBuf(pb, &pt, pencolor);
551
552 for (pt.x = p0->x - dy, pt.y = p0->y - dx;
553 pt.x <= p0->x + dy; pt.x++)
554 plot_PicBuf(pb, &pt, pencolor);
555
556 if (dd < 0) {
557 dd += (4 * dx) + 6;
558 } else {
559 dd += 4 * (dx - dy) + 10;
560 dy--;
561 }
562 }
563 }
564
565
566 static void
line_PicBuf(DevPt * p0,DevPt * p1,PEN_W pensize,PEN_C pencolor,int consecutive,const OUT_PAR * po)567 line_PicBuf(DevPt * p0, DevPt * p1, PEN_W pensize, PEN_C pencolor,
568 int consecutive, const OUT_PAR * po)
569 /**
570 ** Rasterize a vector (draw a line in the picture buffer), using the
571 ** Bresenham algorithm.
572 **/
573 {
574 PicBuf *pb = po->picbuf;
575 DevPt *p_act;
576 DevPt t0, t1, t2, t3;
577 double len, xoff, yoff;
578 int dx, dy;
579 int linewidth = (int) ceil(pensize * po->HP_to_xdots / 0.025); /* convert to pixel space */
580
581 /* printf("pensize = %0.3f mm, linewidth = %d pixels\n",pensize,linewidth);*/
582
583 if (linewidth == 0) /* No pen selected! */
584 return;
585
586 if (pencolor == xxBackground) /* No drawable color! */
587 return;
588
589 if (linewidth < 5)
590 consecutive = 0;
591
592 if (linewidth == 1) { /* Thin lines of any attitude */
593 p_act = bresenham_init(p0, p1);
594 do {
595 plot_PicBuf(pb, p_act, pencolor);
596 } while (bresenham_next() != BRESENHAM_ERR);
597 return;
598 }
599
600 if ((p1->x == p0->x) && (p1->y == p0->y)) { /* No Movement Dot Only */
601 dot_PicBuf(p0, linewidth, pencolor, pb);
602 return;
603 }
604
605 murphy_init(pb, pencolor); /* Wide Lines */
606 murphy_wideline(*p0, *p1, linewidth, consecutive);
607
608 if (pensize > 0.35) {
609 switch (CurrentLineAttr.End) {
610 case LAE_square:
611 dx = p0->x - p1->x;
612 dy = p0->y - p1->y;
613 len = HYPOT(dx, dy);
614 xoff = 0.5 * fabs(dx / len);
615 yoff = 0.5 * fabs(dy / len);
616 t0.x = p0->x - (linewidth - 1) * yoff;
617 t0.y = p0->y + (linewidth - 1) * xoff;
618 t1.x = t0.x - (linewidth - 1) * xoff;
619 t1.y = t0.y + (linewidth - 1) * yoff;
620 t3.x = p0->x - (linewidth - 1) * yoff;
621 t3.y = p0->y - (linewidth - 1) * xoff;
622 t2.x = t3.x - (linewidth - 1) * xoff;
623 t2.y = t3.y + (linewidth - 1) * yoff;
624 polygon_PicBuf(t1, t3, t0, t2, pencolor, pb);
625 t0.x = p1->x + (linewidth - 1) * yoff;
626 t0.y = p1->y + (linewidth - 1) * xoff;
627 t1.x = t0.x + (linewidth - 1) * xoff;
628 t1.y = t0.y + (linewidth - 1) * yoff;
629 t3.x = p1->x + (linewidth - 1) * yoff;
630 t3.y = p1->y - (linewidth - 1) * xoff;
631 t2.x = t3.x + (linewidth - 1) * xoff;
632 t2.y = t3.y + (linewidth - 1) * yoff;
633 polygon_PicBuf(t1, t3, t0, t2, pencolor, pb);
634 break;
635 case LAE_butt:
636 default:
637 break;
638 case LAE_triangular:
639 dx = p0->x - p1->x;
640 dy = p0->y - p1->y;
641 len = HYPOT(dx, dy);
642 xoff = 0.5 * fabs(dx / len);
643 yoff = 0.5 * fabs(dy / len);
644 t0.x = p0->x - (linewidth - 1) * xoff;
645 t0.y = p0->y - (linewidth - 1) * yoff;
646 t1.x = p0->x + (linewidth - 1) * yoff;
647 t1.y = p0->y - (linewidth - 1) * xoff;
648 t2.x = p0->x + (linewidth - 1) * xoff;
649 t2.y = p0->y + (linewidth - 1) * yoff;
650 t3.x = p0->x - (linewidth - 1) * yoff;
651 t3.y = p0->y + (linewidth - 1) * xoff;
652 polygon_PicBuf(t1, t3, t0, t2, pencolor, pb);
653 t0.x = p1->x - (linewidth - 1) * xoff;
654 t0.y = p1->y - (linewidth - 1) * yoff;
655 t1.x = p1->x + (linewidth - 1) * yoff;
656 t1.y = p1->y - (linewidth - 1) * xoff;
657 t2.x = p1->x + (linewidth - 1) * xoff;
658 t2.y = p1->y + (linewidth - 1) * yoff;
659 t3.x = p1->x - (linewidth - 1) * yoff;
660 t3.y = p1->y + (linewidth - 1) * xoff;
661 polygon_PicBuf(t1, t3, t0, t2, pencolor, pb);
662 break;
663 case LAE_round:
664 dot_PicBuf(p0, linewidth, pencolor, pb);
665 dot_PicBuf(p1, linewidth, pencolor, pb);
666 break;
667 }
668 } else {
669 dot_PicBuf(p0, linewidth, pencolor, pb); /* lines upto 0.35 always have round ends */
670 dot_PicBuf(p1, linewidth, pencolor, pb);
671 }
672
673 }
674
polygon_PicBuf(DevPt p4,DevPt p2,DevPt p1,DevPt p3,PEN_C pencolor,PicBuf * pb)675 void polygon_PicBuf(DevPt p4, DevPt p2, DevPt p1, DevPt p3, PEN_C pencolor,
676 PicBuf * pb)
677 {
678
679 DevPt polygon[8];
680 int xmin, ymin, xmax, ymax;
681 int start, end, tmp;
682 DevPt p_act;
683 double denominator;
684 double A1, B1, C1, A2, B2, C2;
685 int scany;
686 int segx, numlines;
687 int i, j, k;
688 /*
689 fprintf (stderr,"in polydraw: (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",p1.x,p1.y,p2.x,p2.y,p3.x,p3.y,
690 p4.x,p4.y);
691 */
692 polygon[0] = p1;
693 polygon[1] = p2;
694 polygon[2] = p2;
695 polygon[3] = p3;
696 polygon[4] = p3;
697 polygon[5] = p4;
698 polygon[6] = p4;
699 polygon[7] = p1;
700 /*
701 fprintf(stderr,"pline0 %d %d - %d %d\n",polygon[0].x,polygon[0].y,polygon[1].x,polygon[1].y);
702 fprintf(stderr,"pline1 %d %d - %d %d\n",polygon[2].x,polygon[2].y,polygon[3].x,polygon[3].y);
703 fprintf(stderr,"pline2 %d %d - %d %d\n",polygon[4].x,polygon[4].y,polygon[5].x,polygon[5].y);
704 fprintf(stderr,"pline3 %d %d - %d %d\n",polygon[6].x,polygon[6].y,polygon[7].x,polygon[7].y);
705 */
706
707 xmin = MIN(p1.x, p2.x);
708 xmin = MIN(xmin, p3.x);
709 xmin = MIN(xmin, p4.x);
710 xmax = MAX(p1.x, p2.x);
711 xmax = MAX(xmax, p3.x);
712 xmax = MAX(xmax, p4.x);
713 ymin = MIN(p1.y, p2.y);
714 ymin = MIN(ymin, p3.y);
715 ymin = MIN(ymin, p4.y);
716 ymax = MAX(p1.y, p2.y);
717 ymax = MAX(ymax, p3.y);
718 ymax = MAX(ymax, p4.y);
719
720 /*
721 xmin=xmin-2;
722 xmax=xmax+2;
723 */
724
725 numlines = 1 + ymax - ymin;
726
727 /* start at lowest y , run scanlines parallel x across polygon */
728 /* looking for intersections with edges */
729
730 for (i = 0; i <= numlines; i++) { /* for all scanlines ... */
731 k = -1;
732 start = end = 0;
733 scany = ymin + i;
734 /*
735 if(scany >= ymax || scany<=ymin) {
736 continue;
737 }
738 */
739 /* coefficients for current scan line */
740 A1 = 0.;
741 B1 = (double) (xmin - xmax);
742 C1 = (double) (scany * (xmax - xmin));
743
744 for (j = 0; j <= 6; j = j + 2) { /*for all polygon edges */
745 if ((scany < MIN(polygon[j].y, polygon[j + 1].y))
746 || (scany >
747 MAX(polygon[j].y, polygon[j + 1].y)))
748 continue;
749
750 /* coefficients for this edge */
751 A2 = (double) (polygon[j + 1].y - polygon[j].y);
752 B2 = (double) (polygon[j].x - polygon[j + 1].x);
753 C2 = (double) (polygon[j].x *
754 (polygon[j].y - polygon[j + 1].y) +
755 polygon[j].y * (polygon[j + 1].x -
756 polygon[j].x));
757
758 /*determine coordinates of intersection */
759 denominator = A1 * B2 - A2 * B1;
760 if (fabs(denominator) > 1.e-5) { /* zero means parallel lines */
761
762 segx = (int) ((B1 * C2 - B2 * C1) / denominator); /*x coordinate of intersection */
763
764 /*fprintf(stderr,"seg x,y= %d %d\n",segx,segy);*/
765 if ((segx > xmax) || (segx < xmin) ||
766 (segx <
767 MIN(polygon[j].x, polygon[j + 1].x))
768 || (segx >
769 MAX(polygon[j].x,
770 polygon[j + 1].x))) {
771 /*fprintf(stderr,"intersection at %d %d is not within (%d,%d)-(%d,%d)\n",segx,segy,polygon[j].x,polygon[j].y,polygon[j+1].x,polygon[j+1].y )
772 ; */
773 } else {
774
775 k++;
776 if (k == 0) {
777 start = segx;
778 } else if (segx != start) {
779 end = segx;
780 } else if (k > 0)
781 k--;
782 } /* if crossing withing range */
783 }
784 /*if not parallel */
785 } /*next edge */
786 if (k >= 1) {
787 if (start > end) {
788 tmp = end;
789 end = start;
790 start = tmp;
791 }
792 /*fprintf(stderr,"fillline %d %d - %d %d\n",start.x,start.y,end.x,end.y);*/
793 for (p_act.x = start, p_act.y = scany;
794 p_act.x <= end; p_act.x++)
795 plot_PicBuf(pb, &p_act, pencolor);
796 }
797 } /* next scanline */
798
799 }
800
tmpfile_to_PicBuf(const GEN_PAR * pg,const OUT_PAR * po)801 void tmpfile_to_PicBuf(const GEN_PAR * pg, const OUT_PAR * po)
802 /**
803 ** Interface to higher-level routines:
804 ** Assuming a valid picture buffer, read the drawing commands from
805 ** the temporary file, transform HP_GL coordinates into dot coordinates,
806 ** and draw (rasterize) vectors.
807 **/
808 {
809 HPGL_Pt pt1;
810 static DevPt ref = { 0, 0 };
811 DevPt next;
812 PlotCmd cmd;
813 static int consecutive = 0;
814 int pen_no = 1;
815
816 if (!pg->quiet)
817 Eprintf("\nPlotting in buffer\n");
818
819 rewind(pg->td);
820
821 while ((cmd = PlotCmd_from_tmpfile()) != CMD_EOF)
822 switch (cmd) {
823 case NOP:
824 break;
825 case SET_PEN:
826 if ((pen_no = fgetc(pg->td)) == EOF) {
827 PError("Unexpected end of temp. file");
828 exit(ERROR);
829 }
830 consecutive = 0;
831 break;
832 case DEF_PW:
833 if (!load_pen_width_table(pg->td)) {
834 PError("Unexpected end of temp. file");
835 exit(ERROR);
836 }
837 break;
838 case DEF_PC:
839 if (load_pen_color_table(pg->td) < 0) {
840 PError("Unexpected end of temp. file");
841 exit(ERROR);
842 }
843 consecutive = 0;
844 break;
845 case DEF_LA:
846 if (load_line_attr(pg->td) < 0) {
847 PError("Unexpected end of temp. file");
848 exit(ERROR);
849 }
850 consecutive = 0;
851 break;
852 case MOVE_TO:
853 HPGL_Pt_from_tmpfile(&pt1);
854 HPcoord_to_dotcoord(&pt1, &ref, po);
855 consecutive = 0;
856 break;
857 case DRAW_TO:
858 HPGL_Pt_from_tmpfile(&pt1);
859 HPcoord_to_dotcoord(&pt1, &next, po);
860 line_PicBuf(&ref, &next, pt.width[pen_no],
861 pt.color[pen_no], consecutive, po);
862 memcpy(&ref, &next, sizeof(ref));
863 consecutive++;
864 break;
865 case PLOT_AT:
866 HPGL_Pt_from_tmpfile(&pt1);
867 HPcoord_to_dotcoord(&pt1, &ref, po);
868 line_PicBuf(&ref, &ref, pt.width[pen_no],
869 pt.color[pen_no], consecutive, po);
870 consecutive = 0;
871 break;
872
873 default:
874 Eprintf("Illegal cmd in temp. file!\n");
875 exit(ERROR);
876 }
877 }
878