1 /* $XConsortium: out_scrn.c,v 1.5 94/02/10 14:15:39 gildea Exp $ */
5 Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
6 You are hereby granted permission under all Bitstream propriety rights to
7 use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
8 software and the Bitstream Charter outline font for any purpose and without
9 restrictions; provided, that this notice is left intact on all copies of such
10 software or font and that Bitstream's trademark is acknowledged as shown below
11 on all unmodified copies of such font.
13 BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
16 BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
17 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
19 DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
20 INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
21 WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
26 /*************************** O U T _ S C R N . C *****************************
28 * This is an output module for screen-writer mode. *
30 *****************************************************************************/
33 #include "spdo_prv.h" /* General definitions for Speedo */
37 #define ABS(X) ( (X < 0) ? -X : X)
41 #define SHOW(X) printf("X = %d\n", X)
47 /***** GLOBAL VARIABLES *****/
49 /***** GLOBAL FUNCTIONS *****/
51 /***** EXTERNAL VARIABLES *****/
53 /***** EXTERNAL FUNCTIONS *****/
55 /***** STATIC VARIABLES *****/
57 /***** STATIC FUNCTIONS *****/
60 static void sp_add_intercept_screen(PROTO_DECL2 fix15 y,fix31 x);
61 static void sp_proc_intercepts_screen(PROTO_DECL1);
63 static void sp_add_intercept_screen();
64 static void sp_proc_intercepts_screen();
69 FUNCTION boolean init_screen(specsarg)
71 specs_t FONTFAR *specsarg;
73 * init_out0() is called by sp_set_specs() to initialize the output module.
74 * Returns TRUE if output module can accept requested specifications.
75 * Returns FALSE otherwise.
79 printf("INIT_SCREEN()\n");
87 FUNCTION boolean begin_char_screen(Psw, Pmin, Pmax)
92 /* Called once at the start of the character generation process
96 printf("BEGIN_CHAR_SCREEN(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
97 (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
98 (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
99 (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
101 if (sp_globals.pixshift > 8)
102 sp_intercepts.fracpix = sp_globals.onepix << (8 - sp_globals.pixshift);
104 sp_intercepts.fracpix = sp_globals.onepix >> (sp_globals.pixshift - 8);
106 init_char_out(Psw,Pmin,Pmax);
114 FUNCTION void begin_contour_screen(P1, outside)
118 /* Called at the start of each contour
123 printf("BEGIN_CONTOUR_SCREEN(%3.1f, %3.1f, %s)\n",
124 (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix, outside? "outside": "inside");
126 sp_globals.x0_spxl = P1.x;
127 sp_globals.y0_spxl = P1.y;
128 sp_globals.y_pxl = (sp_globals.y0_spxl + sp_globals.pixrnd) >> sp_globals.pixshift;
133 FUNCTION void curve_screen(P1, P2, P3, depth)
147 printf("CURVE_SCREEN(%6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f)\n",
148 (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
149 (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
150 (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix);
154 if (sp_globals.extents_running) /* Accumulate actual character extents if required */
156 if (P3.x > sp_globals.bmap_xmax)
157 sp_globals.bmap_xmax = P3.x;
158 if (P3.x < sp_globals.bmap_xmin)
159 sp_globals.bmap_xmin = P3.x;
160 if (P3.y > sp_globals.bmap_ymax)
161 sp_globals.bmap_ymax = P3.y;
162 if (P3.y < sp_globals.bmap_ymin)
163 sp_globals.bmap_ymin = P3.y;
166 X0 = ((fix31)sp_globals.x0_spxl << sp_globals.poshift) + (fix31)32768;
167 Y0 = ((fix31)sp_globals.y0_spxl << sp_globals.poshift) + (fix31)32768;
168 X1 = ((fix31)P1.x << sp_globals.poshift) + (fix31)32768;
169 Y1 = ((fix31)P1.y << sp_globals.poshift) + (fix31)32768;
170 X2 = ((fix31)P2.x << sp_globals.poshift) + (fix31)32768;
171 Y2 = ((fix31)P2.y << sp_globals.poshift) + (fix31)32768;
172 X3 = ((fix31)P3.x << sp_globals.poshift) + (fix31)32768;
173 Y3 = ((fix31)P3.y << sp_globals.poshift) + (fix31)32768;
175 if (((Y0 - Y3) * sp_globals.tcb.mirror) > 0)
177 sp_intercepts.leftedge = LEFT_INT;
181 sp_intercepts.leftedge = 0;
184 scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3);
185 sp_globals.x0_spxl = P3.x;
186 sp_globals.y0_spxl = P3.y;
187 sp_globals.y_pxl = (P3.y + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan sp_globals.line */
190 FUNCTION void scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3)
\f
192 fix31 X0,Y0,X1,Y1,X2,Y2,X3,Y3;
193 /* Called for each curve in the transformed character if curves out enabled
204 printf("SCAN_CURVE_SCREEN(%6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f)\n",
205 (real)(X0-32768) / 65536.0, (real)(Y0-32768) / 65536.0,
206 (real)(X1-32768) / 65536.0, (real)(Y1-32768) / 65536.0,
207 (real)(X2-32768) / 65536.0, (real)(Y2-32768) / 65536.0,
208 (real)(X3-32768) / 65536.0, (real)(Y3-32768) / 65536.0);
211 if (((Y3 >> 16)) == (Y0 >> 16) || (Y3+1) == Y0 || Y3 == (Y0+1))
215 if ((X3 >> 16) == (X0 >> 16))
217 vert_line_screen(X3,(Y0>>16),(Y3>>16));
220 Pmidx = (X0 + (X1 + X2) * 3 + X3 + 4 ) >> 3;
221 Pmidy = (Y0 + (Y1 + Y2) * 3 + Y3 + 4 ) >> 3;
223 Pctrl1x = (X0 + X1 + 1 ) >> 1;
224 Pctrl1y = (Y0 + Y1 + 1) >> 1;
225 Pctrl2x = (X0 + (X1 << 1) + X2 + 2 ) >> 2;
226 Pctrl2y = (Y0 + (Y1 << 1) + Y2 + 2 ) >> 2;
227 scan_curve_screen(X0,Y0, Pctrl1x, Pctrl1y, Pctrl2x,Pctrl2y, Pmidx,Pmidy);
229 Pctrl1x = (X1 + (X2 << 1) + X3 + 2 ) >> 2;
230 Pctrl1y = (Y1 + (Y2 << 1) + Y3 + 2 ) >> 2;
231 Pctrl2x = (X2 + X3 + 1 ) >> 1;
232 Pctrl2y = (Y2 + Y3 + 1 ) >> 1;
233 scan_curve_screen(Pmidx,Pmidy, Pctrl1x,Pctrl1y, Pctrl2x,Pctrl2y, X3,Y3);
236 FUNCTION void vert_line_screen(x,y1,y2)
243 printf("VERT_LINE_SCREEN(%6.4f, %6.4f, %6.4f)\n",
244 (real)(x - 32768) / 65536.0,
245 (real)(y1 - 32768) / 65536.0,
246 (real)(y2 - 32768) / 65536.0);
249 if (sp_globals.intercept_oflo)
252 if (y1 > y2) /* Line goes downwards ? */
254 if (y1 > (sp_globals.y_band.band_max + 1)) /* Start point above top of band? */
255 y1 = sp_globals.y_band.band_max + 1; /* Adjust start point to top of band */
256 if (y2 < sp_globals.y_band.band_min) /* End point below bottom of band? */
257 y2 = sp_globals.y_band.band_min; /* Adjust end point bottom of band */
259 y1 -= sp_globals.y_band.band_min; /* Translate start point to band origin */
260 y2 -= sp_globals.y_band.band_min; /* Translate end point to band origin */
262 while (y2 < y1) /* At least one intercept left? */
264 sp_add_intercept_screen(--y1, x); /* Add intercept */
267 else if (y2 > y1) /* Line goes upwards ? */
269 if (y1 < sp_globals.y_band.band_min) /* Start point below bottom of band? */
270 y1 = sp_globals.y_band.band_min; /* Adjust start point to bottom of band */
271 if (y2 > (sp_globals.y_band.band_max + 1)) /* End point above top of band? */
272 y2 = sp_globals.y_band.band_max + 1; /* Adjust end point to top of band */
274 y1 -= sp_globals.y_band.band_min; /* Translate start point to band origin */
275 y2 -= sp_globals.y_band.band_min; /* Translate end point to band origin */
277 while (y1 < y2) /* At least one intercept left? */
279 sp_add_intercept_screen(y1++, x); /* Add intercept */
290 FUNCTION void line_screen(P1)
293 /* Called for each vector in the transformed character
296 register fix15 how_many_y; /* # of intercepts at y = n + 1/2 */
297 register fix15 yc; /* Current scan-line */
298 fix15 temp1; /* various uses */
299 fix15 temp2; /* various uses */
300 register fix31 dx_dy; /* slope of line in 16.16 form */
301 register fix31 xc; /* high-precision (16.16) x coordinate */
302 fix15 x0,y0,x1,y1; /* PIX.FRAC start and endpoints */
304 x0 = sp_globals.x0_spxl; /* get start of line (== current point) */
305 y0 = sp_globals.y0_spxl;
306 sp_globals.x0_spxl = x1 = P1.x; /* end of line */
307 sp_globals.y0_spxl = y1 = P1.y; /* (also update current point to end of line) */
309 yc = sp_globals.y_pxl; /* current scan line = end of last line */
310 sp_globals.y_pxl = (y1 + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan sp_globals.line */
314 printf("LINE_SCREEN(%3.4f, %3.4f)\n",
315 (real)P1.x/(real)sp_globals.onepix,
316 (real)P1.y/(real)sp_globals.onepix);
319 if (sp_globals.extents_running)
321 if (sp_globals.x0_spxl > sp_globals.bmap_xmax)
322 sp_globals.bmap_xmax = sp_globals.x0_spxl;
323 if (sp_globals.x0_spxl < sp_globals.bmap_xmin)
324 sp_globals.bmap_xmin = sp_globals.x0_spxl;
325 if (sp_globals.y0_spxl > sp_globals.bmap_ymax)
326 sp_globals.bmap_ymax = sp_globals.y0_spxl;
327 if (sp_globals.y0_spxl < sp_globals.bmap_ymin)
328 sp_globals.bmap_ymin = sp_globals.y0_spxl;
331 if (sp_globals.intercept_oflo) return;
333 if ((how_many_y = sp_globals.y_pxl - yc) == 0) return; /* Don't draw a null line */
335 xc = (fix31)(x0 + sp_globals.pixrnd) << (16 - sp_globals.pixshift); /* Original x coordinate with built in */
336 /* rounding. 16.16 form */
340 yc--; /* Predecrment downward lines */
343 if ((how_many_y * sp_globals.tcb.mirror) < 0)
345 sp_intercepts.leftedge = LEFT_INT;
349 sp_intercepts.leftedge = 0;
352 if (yc > sp_globals.y_band.band_max) /* Is start point above band? */
354 if (sp_globals.y_pxl > sp_globals.y_band.band_max) return; /* line has to go down! */
355 how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_max) - 1; /* Yes, limit it */
358 if (yc < sp_globals.y_band.band_min) /* Is start point below band? */
360 if (sp_globals.y_pxl < sp_globals.y_band.band_min) return; /* line has to go up! */
361 how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_min); /* Yes, limit it */
364 if ( (temp1 = (x1 - x0)) == 0) /* check for vertical line */
366 dx_dy = 0L; /* Zero slope, leave xc alone */
370 /* calculate dx_dy at 16.16 fixed point */
372 dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
374 /* We have to check for a @#$%@# possible multiply overflow */
375 /* by doing another @#$*& multiply. In assembly language, */
376 /* the program could just check the OVerflow flag or whatever*/
377 /* works on the particular processor. This C code is meant */
378 /* to be processor independant. */
380 temp1 = (yc << sp_globals.pixshift) - y0 + sp_globals.pixrnd;
381 /* This sees if the sign bits start at bit 15 */
382 /* if they do, no overflow has occurred */
384 temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
386 if ( (temp2 != (fix15)-1) &&
388 { /* Overflow. Pick point closest to yc + .5 */
389 if (ABS(temp1) < ABS((yc << sp_globals.pixshift) - y1 + sp_globals.pixrnd))
390 { /* use x1 instead of x0 */
391 xc = (fix31)(x1 + sp_globals.pixrnd) << (16 - sp_globals.pixshift);
395 /* calculate new xc at the center of the *current* scan line */
396 /* due to banding, yc may be several lines away from y0 */
397 /* xc += (yc + .5 - y0) * dx_dy */
398 /* This multiply generates a subpixel delta. */
399 /* So we shift it to be a 16.16 delta */
401 xc += ((fix31)temp1 * dx_dy) >> sp_globals.pixshift;
405 yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
409 if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
410 while(yc >= how_many_y)
412 sp_add_intercept_screen(yc--,xc);
418 /* check to see that line doesn't extend beyond top of band */
419 if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
420 while(yc != how_many_y)
422 sp_add_intercept_screen(yc++,xc);
430 FUNCTION void end_contour_screen()
432 /* Called after the last vector in each contour
436 printf("END_CONTOUR_SCREEN()\n");
438 sp_intercepts.inttype[sp_globals.next_offset-1] |= END_INT;
445 FUNCTION boolean end_char_screen()
447 /* Called when all character data has been output
448 * Return TRUE if output process is complete
449 * Return FALSE to repeat output of the transformed data beginning
450 * with the first contour
458 fix31 em_max, em_min, bmap_max, bmap_min;
462 printf("END_CHAR_SCREEN()\n");
465 if (sp_globals.first_pass)
467 if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
469 sp_globals.xmin = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
470 sp_globals.xmax = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
474 sp_globals.xmin = sp_globals.xmax = 0;
476 if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
480 switch(sp_globals.tcb0.xtype)
482 case 1: /* 180 degree rotation */
483 if (sp_globals.specs.flags & CLIP_TOP)
485 sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
486 sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
487 bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
488 sp_globals.clip_ymin = -1 * sp_globals.clip_ymin;
489 if (bmap_min < sp_globals.clip_ymin)
490 sp_globals.ymin = sp_globals.clip_ymin;
492 sp_globals.ymin = bmap_min;
494 if (sp_globals.specs.flags & CLIP_BOTTOM)
496 sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
497 sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
498 bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
499 if (bmap_max < sp_globals.clip_ymax)
500 sp_globals.ymax = bmap_max;
502 sp_globals.ymax = sp_globals.clip_ymax;
504 sp_globals.clip_xmax = -sp_globals.xmin;
505 sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
508 case 2: /* 90 degree rotation */
509 if (sp_globals.specs.flags & CLIP_TOP)
511 sp_globals.clip_xmin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
512 sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
513 sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
514 bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
515 if (bmap_min > sp_globals.clip_xmin)
516 sp_globals.clip_xmin = bmap_min;
518 /* normalize to x origin */
519 sp_globals.clip_xmin -= sp_globals.xmin;
521 if (sp_globals.specs.flags & CLIP_BOTTOM)
523 sp_globals.clip_xmax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
524 sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
525 bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
526 if (bmap_max < sp_globals.clip_xmax)
527 sp_globals.xmax = bmap_max;
529 sp_globals.xmax = sp_globals.clip_xmax;
530 sp_globals.clip_ymax = 0;
531 if ((sp_globals.specs.flags & CLIP_TOP) &&
532 (sp_globals.ymax > sp_globals.clip_ymax))
533 sp_globals.ymax = sp_globals.clip_ymax;
534 sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
535 if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
536 (sp_globals.ymin < sp_globals.clip_ymin))
537 sp_globals.ymin = sp_globals.clip_ymin;
538 /* normalize to x origin */
539 sp_globals.clip_xmax -= sp_globals.xmin;
542 case 3: /* 270 degree rotation */
543 if (sp_globals.specs.flags & CLIP_TOP)
545 sp_globals.clip_xmin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
546 sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
547 sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
548 bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
550 /* let the minimum be the larger of these two values */
551 if (bmap_min > sp_globals.clip_xmin)
552 sp_globals.clip_xmin = bmap_min;
554 /* normalize the x value to new xorgin */
555 sp_globals.clip_xmin -= sp_globals.xmin;
557 if (sp_globals.specs.flags & CLIP_BOTTOM)
559 sp_globals.clip_xmax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
560 sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
561 bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
563 /* let the max be the lesser of these two values */
564 if (bmap_max < sp_globals.clip_xmax)
566 sp_globals.xmax = bmap_max;
567 sp_globals.clip_xmax = bmap_max;
570 sp_globals.xmax = sp_globals.clip_xmax;
572 /* normalize the x value to new x origin */
573 sp_globals.clip_xmax -= sp_globals.xmin;
575 /* compute y clip values */
576 sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
577 if ((sp_globals.specs.flags & CLIP_TOP) &&
578 (sp_globals.ymax > sp_globals.clip_ymax))
579 sp_globals.ymax = sp_globals.clip_ymax;
580 sp_globals.clip_ymin = 0;
581 if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
582 (sp_globals.ymin < sp_globals.clip_ymin))
583 sp_globals.ymin = sp_globals.clip_ymin;
585 default: /* this is for zero degree rotation and arbitrary rotation */
586 if (sp_globals.specs.flags & CLIP_TOP)
588 sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
589 sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
590 bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
591 if (bmap_max > sp_globals.clip_ymax)
592 sp_globals.ymax = bmap_max;
594 sp_globals.ymax = sp_globals.clip_ymax;
596 if (sp_globals.specs.flags & CLIP_BOTTOM)
598 sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
599 sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
600 sp_globals.clip_ymin = - sp_globals.clip_ymin;
601 bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
602 if (bmap_min < sp_globals.clip_ymin)
603 sp_globals.ymin = sp_globals.clip_ymin;
605 sp_globals.ymin = bmap_min;
607 sp_globals.clip_xmin = -sp_globals.xmin;
608 sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
612 if ( !(sp_globals.specs.flags & CLIP_TOP))
614 sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
617 if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
620 sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
624 sp_globals.ymin = sp_globals.ymax = 0;
627 /* add in the rounded out part (from xform.) of the left edge */
628 if (sp_globals.tcb.xmode == 0) /* for X pix is function of X orus only add the round */
629 xorg = (((fix31)sp_globals.xmin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
631 if (sp_globals.tcb.xmode == 1) /* for X pix is function of -X orus only, subtr. round */
632 xorg = (((fix31)sp_globals.xmin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift)) ;
634 xorg = (fix31)sp_globals.xmin << 16; /* for other cases don't use round on x */
636 if (sp_globals.tcb.ymode == 2) /* for Y pix is function of X orus only, add round error */
637 yorg = (((fix31)sp_globals.ymin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
639 if (sp_globals.tcb.ymode == 3) /* for Y pix is function of -X orus only, sub round */
640 yorg = (((fix31)sp_globals.ymin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift));
641 else /* all other cases have no round error on yorg */
642 yorg = (fix31)sp_globals.ymin << 16;
644 open_bitmap(sp_globals.set_width.x, sp_globals.set_width.y, xorg, yorg,
645 sp_globals.xmax - sp_globals.xmin, sp_globals.ymax - sp_globals.ymin);
646 if (sp_globals.intercept_oflo)
648 sp_globals.y_band.band_min = sp_globals.ymin;
649 sp_globals.y_band.band_max = sp_globals.ymax;
650 init_intercepts_out();
651 sp_globals.first_pass = FALSE;
652 sp_globals.extents_running = FALSE;
657 sp_proc_intercepts_screen();
664 if (sp_globals.intercept_oflo)
666 reduce_band_size_out();
667 init_intercepts_out();
672 sp_proc_intercepts_screen();
675 init_intercepts_out();
686 FUNCTION LOCAL void sp_add_intercept_screen(y, x)
688 fix15 y; /* Y coordinate in relative pixel units */
689 /* (0 is lowest sample in band) */
690 fix31 x; /* X coordinate of intercept in subpixel units */
692 /* Called by line() to add an intercept to the intercept list structure
696 register fix15 from; /* Insertion pointers for the linked list sort */
699 register fix15 xfrac;
702 printf(" Add intercept(%2d, %x)\n", y + sp_globals.y_band.band_min, x);
704 /* Bounds checking IS done in debug mode */
705 if (y < 0) /* Y value below bottom of current band? */
707 printf(" Intecerpt less than 0!!!\007\n");
711 if (y > (sp_globals.no_y_lists - 1)) /* Y value above top of current band? */
713 printf(" Intercept too big for band!!!!!\007\n");
718 /* Store new values */
720 sp_intercepts.car[sp_globals.next_offset] = xloc = (fix15)(x >> 16);
721 sp_intercepts.inttype[sp_globals.next_offset] = sp_intercepts.leftedge | (xfrac = ((x >> 8) & FRACTION));
723 /* Find slot to insert new element (between from and to) */
725 from = y; /* Start at list head */
727 while( (to = sp_intercepts.cdr[from]) != 0) /* Until to == end of list */
729 if (xloc < sp_intercepts.car[to]) /* If next item is larger than or same as this one... */
730 goto insert_element; /* ... drop out and insert here */
731 else if (xloc == sp_intercepts.car[to] && xfrac < (sp_intercepts.inttype[to] & FRACTION))
732 goto insert_element; /* ... drop out and insert here */
733 from = to; /* move forward in list */
736 insert_element: /* insert element "sp_globals.next_offset" between elements "from" */
739 sp_intercepts.cdr[from] = sp_globals.next_offset;
740 sp_intercepts.cdr[sp_globals.next_offset] = to;
742 if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
744 sp_globals.intercept_oflo = TRUE;
745 /* There may be a few more calls to "add_intercept" from the current line */
746 /* To avoid problems, we set next_offset to a safe value. We don't care */
747 /* if the intercept table gets trashed at this point */
748 sp_globals.next_offset = sp_globals.first_offset;
755 FUNCTION LOCAL void sp_proc_intercepts_screen()
758 /* Called by sp_make_char to output accumulated intercept lists
759 * Clips output to sp_globals.xmin, sp_globals.xmax, sp_globals.ymin, sp_globals.ymax boundaries
762 register fix15 i,j, jplus1, iminus1;
763 fix15 k,nextk, previ;
764 register fix15 from, to; /* Start and end of run in pixel units
765 relative to left extent of character */
767 register fix15 scan_line;
768 fix15 first_y, last_y;
771 boolean clipleft, clipright;
777 printf("\nPROC_INTERCEPTS_SCREEN: Intercept lists before:\n");
781 if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
785 if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
789 if (clipleft || clipright)
791 xmax = sp_globals.clip_xmax + sp_globals.xmin;
792 xmin = sp_globals.clip_xmin + sp_globals.xmin;
795 xmax = ((sp_globals.set_width.x+32768L) >> 16);
798 if ((first_y = sp_globals.y_band.band_max) >= sp_globals.ymax)
799 first_y = sp_globals.ymax - 1; /* Clip to sp_globals.ymax boundary */
801 if ((last_y = sp_globals.y_band.band_min) < sp_globals.ymin)
802 last_y = sp_globals.ymin; /* Clip to sp_globals.ymin boundary */
804 last_y -= sp_globals.y_band.band_min;
807 /* Print out all of the intercept info */
808 scan_line = sp_globals.ymax - first_y - 1;
810 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
812 i = y; /* Index head of intercept list */
813 while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
815 if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
816 from = 0; /* Clip to sp_globals.xmin boundary */
817 i = sp_intercepts.cdr[i]; /* Link to next intercept */
818 if (i == 0) /* End of list? */
820 printf("****** proc_intercepts: odd number of intercepts\n");
823 if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
824 to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
826 to -= sp_globals.xmin;
827 printf(" Y = %2d (scanline %2d): %d %d:\n",
828 y + sp_globals.y_band.band_min, scan_line, from, to);
833 /* CHECK INTERCEPT LIST FOR DROPOUT AND WINDING, FIX IF NECESSARY */
835 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--)
838 i = sp_intercepts.cdr[y]; /* Index head of intercept list */
839 while (i != 0) /* Link to next intercept if present */
842 i = sp_intercepts.cdr[i]; /* Link to next intercept */
843 if (sp_intercepts.inttype[i] & LEFT_INT)
845 if (sp_intercepts.inttype[j] & LEFT_INT)
847 do { i = sp_intercepts.cdr[i]; } while (sp_intercepts.inttype[i] & LEFT_INT);
848 do { i = sp_intercepts.cdr[i]; } while (sp_intercepts.cdr[i] && !(sp_intercepts.inttype[sp_intercepts.cdr[i]] & LEFT_INT));
849 sp_intercepts.cdr[j] = i;
853 xsave = sp_intercepts.car[j];
854 sp_intercepts.car[j] = sp_intercepts.car[i];
855 sp_intercepts.car[i] = xsave;
857 xsave = sp_intercepts.inttype[j];
858 sp_intercepts.inttype[j] = sp_intercepts.inttype[i] & FRACTION;
859 sp_intercepts.inttype[i] = xsave | LEFT_INT;
861 sp_intercepts.cdr[previ] = i;
862 sp_intercepts.cdr[j] = sp_intercepts.cdr[i];
863 sp_intercepts.cdr[i] = j;
865 j = sp_intercepts.cdr[previ];
869 if (sp_intercepts.car[j] < sp_globals.xmin)
870 sp_intercepts.car[j] = sp_globals.xmin; /* Clip to sp_globals.xmin boundary */
872 if (sp_intercepts.car[i] > sp_globals.xmax)
873 sp_intercepts.car[i] = sp_globals.xmax;
875 if (sp_intercepts.car[j] >= sp_intercepts.car[i])
877 if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i] & FRACTION) > sp_intercepts.fracpix)
878 ++sp_intercepts.car[i];
880 --sp_intercepts.car[j];
882 if (sp_globals.first_pass)
884 if (sp_intercepts.inttype[i-1] & END_INT)
886 for (iminus1 = i+1; !(sp_intercepts.inttype[iminus1] & END_INT); iminus1++)
892 if (sp_intercepts.inttype[j] & END_INT)
894 for (jplus1 = j-1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1--)
901 if ((sp_intercepts.inttype[iminus1] & LEFT_INT))
903 if ( sp_intercepts.car[jplus1] > sp_intercepts.car[i])
905 diff = sp_intercepts.car[jplus1] - sp_intercepts.car[i];
906 sp_intercepts.car[i] += diff/2;
907 sp_intercepts.car[jplus1] -= diff/2;
910 if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) > sp_intercepts.fracpix)
911 sp_intercepts.car[i] ++;
913 sp_intercepts.car[jplus1]--;
917 else if (!(sp_intercepts.inttype[jplus1] & LEFT_INT))
919 if (sp_intercepts.car[iminus1] < sp_intercepts.car[j])
921 diff = sp_intercepts.car[j] - sp_intercepts.car[iminus1];
922 sp_intercepts.car[j] -= diff/2;
923 sp_intercepts.car[iminus1] += diff/2;
926 if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) +
927 (ufix16)(sp_intercepts.inttype[iminus1] & FRACTION) > sp_intercepts.fracpix)
928 sp_intercepts.car[iminus1]++;
930 sp_intercepts.car[j]--;
934 if (sp_globals.tcb.mirror == -1)
936 if (sp_intercepts.inttype[j-1] & END_INT)
938 for (jplus1 = j+1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1++)
947 if (!(sp_intercepts.inttype[jplus1] & LEFT_INT) &&
948 sp_intercepts.car[j] > sp_intercepts.car[jplus1])
950 k = sp_intercepts.cdr[y - 1];
953 nextk = sp_intercepts.cdr[k];
954 if (!(sp_intercepts.inttype[k] & LEFT_INT) &&
955 (sp_intercepts.inttype[nextk] & LEFT_INT) &&
956 sp_intercepts.car[nextk] > sp_intercepts.car[jplus1])
958 if ((diff=sp_intercepts.car[j] - sp_intercepts.car[k]) > 0)
960 if (diff <= (sp_intercepts.car[nextk] - sp_intercepts.car[jplus1]))
962 sp_intercepts.car[j] -= diff/2;
963 sp_intercepts.car[k] += diff/2;
966 if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) +
967 (ufix16)(sp_intercepts.inttype[k] & FRACTION) > sp_intercepts.fracpix)
968 sp_intercepts.car[j]--;
970 sp_intercepts.car[k]++;
975 diff = sp_intercepts.car[nextk] - sp_intercepts.car[jplus1];
976 sp_intercepts.car[nextk] -= diff/2;
977 sp_intercepts.car[jplus1] += diff/2;
980 if ((ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) +
981 (ufix16)(sp_intercepts.inttype[nextk] & FRACTION) > sp_intercepts.fracpix)
982 sp_intercepts.car[nextk]--;
984 sp_intercepts.car[jplus1]++;
993 if (j > 0 && sp_intercepts.car[j-1] > sp_intercepts.car[i] && !(sp_intercepts.inttype[j-1] & END_INT))
995 diff = sp_intercepts.car[j-1] - sp_intercepts.car[i];
996 sp_intercepts.car[i] += diff/2;
997 sp_intercepts.car[j-1] -= diff/2;
1000 if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[j-1] & FRACTION) > sp_intercepts.fracpix)
1001 sp_intercepts.car[i]++;
1003 sp_intercepts.car[j-1]--;
1006 if (sp_intercepts.car[i+1] < sp_intercepts.car[j] && !(sp_intercepts.inttype[i] & END_INT))
1008 diff = sp_intercepts.car[j] - sp_intercepts.car[i+1];
1009 sp_intercepts.car[j] -= diff/2;
1010 sp_intercepts.car[i+1] += diff/2;
1013 if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i+1] & FRACTION) > sp_intercepts.fracpix)
1014 sp_intercepts.car[i+1]++;
1016 sp_intercepts.car[j]--;
1022 i = sp_intercepts.cdr[i];
1027 printf("\nPROC_INTERCEPTS_SCREEN: Intercept lists after:\n");
1028 /* Print out all of the intercept info */
1029 scan_line = sp_globals.ymax - first_y - 1;
1031 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
1033 i = y; /* Index head of intercept list */
1034 while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
1036 if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
1037 from = 0; /* Clip to sp_globals.xmin boundary */
1038 i = sp_intercepts.cdr[i]; /* Link to next intercept */
1039 if (i == 0) /* End of list? */
1041 printf("****** proc_intercepts: odd number of intercepts\n");
1044 if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
1045 to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
1047 to -= sp_globals.xmin;
1048 printf(" Y = %2d (scanline %2d): %d %d:\n",
1049 y + sp_globals.y_band.band_min, scan_line, from, to);
1054 /* INTERCEPTS ALL PATCHED, NOW DRAW THE IMAGE */
1055 scan_line = sp_globals.ymax - first_y - 1;
1057 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
1059 i = sp_intercepts.cdr[y]; /* Index head of intercept list */
1060 while (i != 0) /* Link to next intercept if present */
1062 from = sp_intercepts.car[i];
1063 i = sp_intercepts.cdr[i]; /* Link to next intercept */
1064 to = sp_intercepts.car[i];
1070 i = sp_intercepts.cdr[i];
1080 i = sp_intercepts.cdr[i];
1087 set_bitmap_bits(scan_line, from-sp_globals.xmin, to-sp_globals.xmin);
1088 i = sp_intercepts.cdr[i];