]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/Speedo/out_blk.c
57773da6a8f6962a62957e9855cb47946eae6821
[rdpsrv] / Xserver / lib / font / Speedo / out_blk.c
1 /* $XConsortium: out_blk.c,v 1.4 94/02/07 10:01:11 gildea Exp $ */
2
3 /*
4
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.
12
13 BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
14
15
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.
22
23 */
24
25
26
27 /*************************** O U T _ B L K . C *********************************
28  *                                                                           *
29  * This is an output module for black-writer mode.                           *
30  *                                                                           *
31  *****************************************************************************/
32
33
34 #include "spdo_prv.h"               /* General definitions for Speedo   */
35
36 #define   DEBUG      0
37 #define   LOCAL      static
38 #define   ABS(X)     ( (X < 0) ? -X : X)
39
40 #if DEBUG
41 #include <stdio.h>
42 #define SHOW(X) printf("X = %d\n", X)
43 #else
44 #define SHOW(X)
45 #endif
46
47
48 /***** GLOBAL VARIABLES *****/
49
50 /***** GLOBAL FUNCTIONS *****/
51
52 /***** EXTERNAL VARIABLES *****/
53
54 /***** EXTERNAL FUNCTIONS *****/
55
56 /***** STATIC VARIABLES *****/
57
58 /***** STATIC FUNCTIONS *****/
59
60 #if INCL_BLACK
61 #if PROTOS_AVAIL
62 static void sp_add_intercept_black(PROTO_DECL2 fix15 y, fix15 x);
63 static void sp_proc_intercepts_black(PROTO_DECL1);
64 #else
65 static void    sp_add_intercept_black();
66 static void    sp_proc_intercepts_black();
67 #endif
68 #endif
69
70 \f
71 #if INCL_BLACK
72 FUNCTION boolean init_black(specsarg)
73 GDECL
74 specs_t GLOBALFAR *specsarg;
75 /*
76  * init_out0() is called by sp_set_specs() to initialize the output module.
77  * Returns TRUE if output module can accept requested specifications.
78  * Returns FALSE otherwise.
79  */
80 {
81 #if DEBUG
82 printf("INIT_BLK()\n");
83 #endif
84 if (specsarg->flags & CURVES_OUT)
85     return FALSE;           /* Curves out not supported */
86 return (TRUE);
87 }
88 #endif
89
90
91 #if INCL_BLACK
92 FUNCTION boolean begin_char_black(Psw, Pmin, Pmax)
93 GDECL
94 point_t Psw;                   
95 point_t Pmin;                   
96 point_t Pmax;                   
97 /* Called once at the start of the character generation process
98  */
99 {
100 #if DEBUG
101 printf("BEGIN_CHAR_BLACK(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n", 
102                     (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
103                     (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
104                     (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
105 #endif
106 init_char_out(Psw,Pmin,Pmax);
107 return TRUE;
108 }
109 #endif
110
111 \f
112 #if INCL_BLACK
113 FUNCTION void begin_contour_black(P1, outside)
114 GDECL
115 point_t P1;                   
116 boolean outside;
117 /* Called at the start of each contour
118  */
119 {
120
121 #if DEBUG
122 printf("BEGIN_CONTOUR_BLACK(%3.1f, %3.1f, %s)\n", 
123     (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix, outside? "outside": "inside");
124 #endif
125 sp_globals.x0_spxl = P1.x;
126 sp_globals.y0_spxl = P1.y;
127 sp_globals.y_pxl = (sp_globals.y0_spxl + sp_globals.pixrnd) >> sp_globals.pixshift;
128 }
129 #endif
130 \f
131 #if INCL_BLACK
132 FUNCTION void line_black(P1)
133 GDECL
134 point_t P1;                   
135 /* Called for each vector in the transformed character
136  */
137 {
138 register fix15     how_many_y;       /* # of intercepts at y = n + 1/2  */
139 register fix15     yc, i;            /* Current scan-line */
140          fix15     temp1;            /* various uses */
141          fix15     temp2;            /* various uses */
142 register fix31     dx_dy;            /* slope of line in 16.16 form */
143 register fix31     xc;               /* high-precision (16.16) x coordinate */
144          fix15     x0,y0,x1,y1;      /* PIX.FRAC start and endpoints */
145
146 x0 = sp_globals.x0_spxl;                 /* get start of line (== current point) */
147 y0 = sp_globals.y0_spxl;
148 sp_globals.x0_spxl = x1 = P1.x; /* end of line */
149 sp_globals.y0_spxl = y1 = P1.y; /*  (also update current point to end of line) */
150
151 yc = sp_globals.y_pxl;                   /* current scan line = end of last line */
152 sp_globals.y_pxl = (y1 + sp_globals.pixrnd) >> sp_globals.pixshift;   /* calculate new end-scan sp_globals.line */
153
154
155 #if DEBUG
156 printf("LINE_BLACK(%3.4f, %3.4f)\n", 
157        (real)P1.x/(real)sp_globals.onepix, 
158        (real)P1.y/(real)sp_globals.onepix);
159 #endif
160
161 if (sp_globals.extents_running)
162     {
163     if (sp_globals.x0_spxl > sp_globals.bmap_xmax)         
164         sp_globals.bmap_xmax = sp_globals.x0_spxl;
165     if (sp_globals.x0_spxl < sp_globals.bmap_xmin)
166         sp_globals.bmap_xmin = sp_globals.x0_spxl;
167     if (sp_globals.y0_spxl > sp_globals.bmap_ymax)
168         sp_globals.bmap_ymax = sp_globals.y0_spxl;
169     if (sp_globals.y0_spxl < sp_globals.bmap_ymin)
170         sp_globals.bmap_ymin = sp_globals.y0_spxl;
171     }
172
173 if (sp_globals.intercept_oflo) return;
174
175 if ((how_many_y = sp_globals.y_pxl - yc) == 0) return; /* Don't draw a null line */
176
177 if (how_many_y < 0) yc--; /* Predecrment downward lines */
178
179 if (yc > sp_globals.y_band.band_max) /* Is start point above band? */
180     {
181     if (sp_globals.y_pxl > sp_globals.y_band.band_max) return; /* line has to go down! */
182     how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_max) - 1; /* Yes, limit it */
183     }
184
185 if (yc < sp_globals.y_band.band_min)   /* Is start point below band? */
186     {
187     if (sp_globals.y_pxl < sp_globals.y_band.band_min) return; /* line has to go up! */
188     how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_min);   /* Yes, limit it */
189     }
190
191 xc = (fix31)(x0 + sp_globals.pixrnd) << (16 - sp_globals.pixshift); /* Original x coordinate with built in  */
192                                             /* rounding. 16.16 form */
193
194
195 if ( (temp1 = (x1 - x0)) == 0)  /* check for vertical line */
196     {
197     yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
198     temp1 = (fix15)(xc >> 16); 
199     if (how_many_y < 0)
200         {   /* Vector down */
201         if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
202         for (i = yc; i >= how_many_y; i--)
203             sp_add_intercept_black(i,temp1); 
204         }
205     else
206         {   /* Vector up */
207      /* check to see that line doesn't extend beyond top of band */
208         if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
209         for (i = yc; i != how_many_y; i++)
210             sp_add_intercept_black(i,temp1); 
211         }
212     return;
213     }
214           
215 /* calculate dx_dy at 16.16 fixed point */
216
217 dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
218
219 /* We have to check for a @#$%@# possible multiply overflow  */
220 /* by doing another @#$*& multiply.  In assembly language,   */
221 /* the program could just check the OVerflow flag or whatever*/
222 /* works on the particular processor.  This C code is meant  */
223 /* to be processor independant.                              */
224
225 temp1 = (yc << sp_globals.pixshift) - y0 + sp_globals.pixrnd;
226 /* This sees if the sign bits start at bit 15 */
227 /* if they do, no overflow has occurred       */
228
229 temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
230
231 if (  (temp2 != (fix15)0xFFFF) &&
232       (temp2 != 0x0000) &&
233       /* Overflow. Pick point closest to yc + .5 */
234     (ABS(temp1) < ABS((yc << sp_globals.pixshift) - y1 + sp_globals.pixrnd)) )
235     { /* use x1 instead of x0 */
236     xc = (fix31)(x1 + sp_globals.pixrnd) << (16 - sp_globals.pixshift);
237     }
238 else
239     {
240 /* calculate new xc at the center of the *current* scan line */
241 /* due to banding, yc may be several lines away from y0      */
242 /*  xc += (yc + .5 - y0) * dx_dy */
243 /* This multiply generates a subpixel delta. */
244 /* So we shift it to be a 16.16 delta */
245
246     xc += ((fix31)temp1 * dx_dy) >> sp_globals.pixshift;
247     }
248
249 yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
250
251 if (how_many_y < 0)
252     {   /* Vector down */
253     if (how_many_y == -1)
254         sp_add_intercept_black(yc, (fix15) (xc >> 16));
255     else
256         {
257         if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
258         for (i = yc; i >= how_many_y; i--)
259             {
260             temp1 = (fix15)(xc >> 16); 
261             sp_add_intercept_black(i,temp1); 
262             xc -= dx_dy;
263             }
264         }
265     }
266     else
267     {   /* Vector up */
268      /* check to see that line doesn't extend beyond top of band */
269     if (how_many_y == 1)
270         sp_add_intercept_black(yc, (fix15) (xc >> 16));
271     else
272         {
273         if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
274         for (i = yc; i != how_many_y; i++)
275             {
276             temp1 = (fix15)(xc >> 16);
277             sp_add_intercept_black(i,temp1); 
278             xc += dx_dy;
279             }
280         }
281     }
282 }
283 #endif
284 #if INCL_BLACK
285 FUNCTION boolean end_char_black()
286 GDECL
287 /* Called when all character data has been output
288  * Return TRUE if output process is complete
289  * Return FALSE to repeat output of the transformed data beginning
290  * with the first contour
291  */
292 {
293
294 fix31 xorg;
295 fix31 yorg;
296 #if INCL_CLIPPING
297 fix31 bmap_max, bmap_min;
298 #endif
299
300 #if DEBUG
301 printf("END_CHAR_BLACK()\n");
302 #endif
303
304 if (sp_globals.first_pass)
305     {
306     if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
307         {
308         sp_globals.xmin = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
309         sp_globals.xmax = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
310         }
311     else
312         {
313         sp_globals.xmin = sp_globals.xmax = 0;
314         }
315     if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
316         {
317
318 #if INCL_CLIPPING
319     switch(sp_globals.tcb0.xtype)
320        {
321        case 1: /* 180 degree rotation */
322             if (sp_globals.specs.flags & CLIP_TOP)
323                {
324                sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
325                sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
326                bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
327                sp_globals.clip_ymin = -1 * sp_globals.clip_ymin;
328                if (bmap_min < sp_globals.clip_ymin)
329                     sp_globals.ymin = sp_globals.clip_ymin;
330                else
331                     sp_globals.ymin = bmap_min;
332                }
333             if (sp_globals.specs.flags & CLIP_BOTTOM)
334                {
335                sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
336                sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
337                bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
338                if (bmap_max < sp_globals.clip_ymax)
339                     sp_globals.ymax = bmap_max;
340                else
341                     sp_globals.ymax = sp_globals.clip_ymax;
342                }
343                sp_globals.clip_xmax =  -sp_globals.xmin;
344                sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
345                                       sp_globals.xmin;
346                break;
347        case 2: /* 90 degree rotation */
348             if (sp_globals.specs.flags & CLIP_TOP)
349                {
350                sp_globals.clip_xmin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
351                sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
352                sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
353                bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
354                if (bmap_min > sp_globals.clip_xmin)
355                     sp_globals.clip_xmin = bmap_min;
356
357                /* normalize to x origin */
358                sp_globals.clip_xmin -= sp_globals.xmin;
359                }
360             if (sp_globals.specs.flags & CLIP_BOTTOM)
361                {
362                sp_globals.clip_xmax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
363                sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
364                bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
365                if (bmap_max < sp_globals.clip_xmax)
366                     sp_globals.xmax = bmap_max;
367                else
368                     sp_globals.xmax = sp_globals.clip_xmax;
369                sp_globals.clip_ymax = 0;
370                if ((sp_globals.specs.flags & CLIP_TOP) && 
371                    (sp_globals.ymax > sp_globals.clip_ymax))
372                     sp_globals.ymax = sp_globals.clip_ymax;
373                sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
374                if ((sp_globals.specs.flags & CLIP_BOTTOM) && 
375                    (sp_globals.ymin < sp_globals.clip_ymin))
376                     sp_globals.ymin = sp_globals.clip_ymin;
377                /* normalize to x origin */
378                sp_globals.clip_xmax -= sp_globals.xmin;
379                }
380                break;
381        case 3: /* 270 degree rotation */
382             if (sp_globals.specs.flags & CLIP_TOP)
383                {
384                sp_globals.clip_xmin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
385                sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
386                sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
387                bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
388
389                /* let the minimum be the larger of these two values */
390                if (bmap_min > sp_globals.clip_xmin)
391                     sp_globals.clip_xmin = bmap_min;
392
393                /* normalize the x value to new xorgin */
394                sp_globals.clip_xmin -= sp_globals.xmin;
395                }
396             if (sp_globals.specs.flags & CLIP_BOTTOM)
397                {
398                sp_globals.clip_xmax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
399                sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
400                bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
401
402                /* let the max be the lesser of these two values */
403                if (bmap_max < sp_globals.clip_xmax)
404                     {
405                     sp_globals.xmax = bmap_max; 
406                     sp_globals.clip_xmax = bmap_max;
407                     }
408                else
409                     sp_globals.xmax = sp_globals.clip_xmax;
410
411                /* normalize the x value to new x origin */
412                sp_globals.clip_xmax -= sp_globals.xmin;
413                }
414                /* compute y clip values */
415                sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
416                if ((sp_globals.specs.flags & CLIP_TOP) && 
417                    (sp_globals.ymax > sp_globals.clip_ymax))
418                     sp_globals.ymax = sp_globals.clip_ymax;
419                sp_globals.clip_ymin = 0;
420                if ((sp_globals.specs.flags & CLIP_BOTTOM) && 
421                    (sp_globals.ymin < sp_globals.clip_ymin))
422                     sp_globals.ymin = sp_globals.clip_ymin;
423                break;
424        default: /* this is for zero degree rotation and arbitrary rotation */
425             if (sp_globals.specs.flags & CLIP_TOP)
426                {
427                sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
428                sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
429                bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
430                if (bmap_max > sp_globals.clip_ymax)
431                     sp_globals.ymax = bmap_max;
432                else
433                     sp_globals.ymax = sp_globals.clip_ymax;
434                }
435             if (sp_globals.specs.flags & CLIP_BOTTOM)
436                {
437                sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo +  ((1<<sp_globals.multshift)/2));
438                sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
439                sp_globals.clip_ymin = - sp_globals.clip_ymin;
440                bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
441                if (bmap_min < sp_globals.clip_ymin)
442                     sp_globals.ymin = sp_globals.clip_ymin;
443                else
444                     sp_globals.ymin = bmap_min;
445                }
446                sp_globals.clip_xmin = -sp_globals.xmin;
447                sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
448                                       sp_globals.xmin;
449                break;
450        }
451 if ( !(sp_globals.specs.flags & CLIP_TOP))
452 #endif
453             sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
454
455 #if INCL_CLIPPING
456 if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
457 #endif
458
459         sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
460         }
461     else
462         {
463         sp_globals.ymin = sp_globals.ymax = 0;
464         }
465
466     /* add in the rounded out part (from xform.) of the left edge */
467     if (sp_globals.tcb.xmode == 0)    /* for X pix is function of X orus only add the round */
468         xorg = (((fix31)sp_globals.xmin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
469     else
470         if (sp_globals.tcb.xmode == 1) /* for X pix is function of -X orus only, subtr. round */
471                 xorg = (((fix31)sp_globals.xmin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift)) ;
472         else
473                 xorg = (fix31)sp_globals.xmin << 16;   /* for other cases don't use round on x */
474            
475     if (sp_globals.tcb.ymode == 2)   /* for Y pix is function of X orus only, add round error */ 
476         yorg = (((fix31)sp_globals.ymin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
477     else
478         if (sp_globals.tcb.ymode == 3) /* for Y pix is function of -X orus only, sub round */
479                 yorg = (((fix31)sp_globals.ymin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift));
480         else                          /* all other cases have no round error on yorg */
481                 yorg = (fix31)sp_globals.ymin << 16;
482
483     open_bitmap(sp_globals.set_width.x, sp_globals.set_width.y, xorg, yorg,
484                                  sp_globals.xmax - sp_globals.xmin, sp_globals.ymax -  sp_globals.ymin);
485     if (sp_globals.intercept_oflo)
486         {
487         sp_globals.y_band.band_min = sp_globals.ymin;
488         sp_globals.y_band.band_max = sp_globals.ymax;
489         init_intercepts_out();
490         sp_globals.first_pass = FALSE;
491         sp_globals.extents_running = FALSE;
492         return FALSE;
493         }
494     else
495         {
496         sp_proc_intercepts_black();
497         close_bitmap();
498         return TRUE;
499         }
500     }
501 else
502     {
503     if (sp_globals.intercept_oflo)
504         {
505         reduce_band_size_out();
506         init_intercepts_out();
507         return FALSE;
508         }
509     else
510         {
511         sp_proc_intercepts_black();
512         if (next_band_out())
513             {
514             init_intercepts_out();
515             return FALSE;
516             }
517         close_bitmap();
518         return TRUE;
519         }
520     }
521 }
522 #endif
523 \f
524 #if INCL_BLACK
525 FUNCTION LOCAL  void sp_add_intercept_black(y, x)
526 GDECL
527 fix15 y;                 /* Y coordinate in relative pixel units */
528                          /* (0 is lowest sample in band) */
529 fix15 x;                 /* X coordinate of intercept in subpixel units */
530
531 /*  Called by line() to add an intercept to the intercept list structure
532  */
533
534 {
535 register fix15 from;   /* Insertion pointers for the linked list sort */
536 register fix15 to;
537
538 #if DEBUG
539 printf("    Add intercept(%2d, %d)\n", y + sp_globals.y_band.band_min,x);
540
541 /* Bounds checking IS done in debug mode */
542 if (y < 0)       /* Y value below bottom of current band? */
543     {
544     printf(" Intecerpt less than 0!!!\007\n");
545     return;
546     }
547
548 if (y > (sp_globals.no_y_lists - 1))              /* Y value above top of current band? */
549     {
550     printf(" Intercept too big for band!!!!!\007\n");
551     return;
552     }
553 #endif
554
555 /* Store new values */
556
557 sp_intercepts.car[sp_globals.next_offset] = x;
558
559 /* Find slot to insert new element (between from and to) */
560
561 from = y; /* Start at list head */
562
563 while( (to = sp_intercepts.cdr[from]) >= sp_globals.first_offset) /* Until to == end of list */
564     {
565     if (x <= sp_intercepts.car[to]) /* If next item is larger than or same as this one... */
566         goto insert_element; /* ... drop out and insert here */
567     from = to; /* move forward in list */
568     }
569
570 insert_element: /* insert element "sp_globals.next_offset" between elements "from" */
571                 /* and "to" */
572
573 sp_intercepts.cdr[from] = sp_globals.next_offset;
574 sp_intercepts.cdr[sp_globals.next_offset] = to;
575
576 if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
577     {
578     sp_globals.intercept_oflo = TRUE;
579 /* There may be a few more calls to "add_intercept" from the current line */
580 /* To avoid problems, we set next_offset to a safe value. We don't care   */
581 /* if the intercept table gets trashed at this point                      */
582     sp_globals.next_offset = sp_globals.first_offset;
583     }
584 }
585
586 #endif
587 \f
588 #if INCL_BLACK
589 FUNCTION LOCAL  void sp_proc_intercepts_black()
590 GDECL
591
592 /*  Called by sp_make_char to output accumulated intercept lists
593  *  Clips output to sp_globals.xmin, sp_globals.xmax, sp_globals.ymin, sp_globals.ymax boundaries
594  */
595 {
596 register fix15 i;
597 register fix15 from, to;          /* Start and end of run in pixel units   
598                             relative to left extent of character  */
599 register fix15 y;
600 register fix15 scan_line;
601          fix15 first_y, last_y;
602          fix15 xmin, xmax;
603          boolean clipleft, clipright;
604
605 #if DEBUG
606 printf("\nIntercept lists:\n");
607 #endif
608
609 #if INCL_CLIPPING
610 if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
611     clipleft = TRUE;
612 else
613     clipleft = FALSE;
614 if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
615     clipright = TRUE;
616 else
617     clipright = FALSE;
618 if (clipleft || clipright)
619         {
620         xmax = sp_globals.clip_xmax;
621         xmin = sp_globals.clip_xmin;
622         }
623 if (!clipright)
624         xmax = ((sp_globals.set_width.x+32768L) >> 16);
625 #endif
626
627 if ((first_y = sp_globals.y_band.band_max) >= sp_globals.ymax)    
628     first_y = sp_globals.ymax - 1;               /* Clip to sp_globals.ymax boundary */
629
630 if ((last_y = sp_globals.y_band.band_min) < sp_globals.ymin)      
631     last_y = sp_globals.ymin;                    /* Clip to sp_globals.ymin boundary */
632
633 last_y  -= sp_globals.y_band.band_min;
634 #if DEBUG
635 /* Print out all of the intercept info */
636 scan_line = sp_globals.ymax - first_y - 1;
637
638 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
639     {
640     i = y;                            /* Index head of intercept list */
641     while ((i = sp_intercepts.cdr[i]) != 0)         /* Link to next intercept if present */
642         {
643         if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
644             from = 0;                 /* Clip to sp_globals.xmin boundary */
645         i = sp_intercepts.cdr[i];                   /* Link to next intercept */
646         if (i == 0)                   /* End of list? */
647             {
648             printf("****** proc_intercepts: odd number of intercepts\n");
649             break;
650             }
651         if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
652             to = sp_globals.xmax - sp_globals.xmin;         /* Clip to sp_globals.xmax boundary */
653         else
654             to -= sp_globals.xmin;
655         printf("    Y = %2d (scanline %2d): %d %d:\n", 
656             y + sp_globals.y_band.band_min, scan_line, from, to);
657         }
658     }
659 #endif
660
661 /* Draw the image */
662 scan_line = sp_globals.ymax - first_y - 1;
663
664 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
665     {
666     i = y;                            /* Index head of intercept list */
667     while ((i = sp_intercepts.cdr[i]) != 0)         /* Link to next intercept if present */
668         {
669         if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
670             from = 0;                 /* Clip to sp_globals.xmin boundary */
671         i = sp_intercepts.cdr[i];                   /* Link to next intercept */
672
673         if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
674             to = sp_globals.xmax - sp_globals.xmin;         /* Clip to sp_globals.xmax boundary */
675         else
676             to -= sp_globals.xmin;
677         if (from >= to)
678                         {
679                         if (from >= sp_globals.xmax - sp_globals.xmin)
680                                 {
681                                 --from ;
682                                 }
683                         to = from+1;
684                         }
685 #if INCL_CLIPPING
686                 if (clipleft)
687                         {
688                         if (to <= xmin)
689                                 continue;
690                         if (from < xmin)
691                                 from = xmin;
692                         }
693         if (clipright)
694                         {
695                         if (from >= xmax)
696                                 continue;
697                         if (to > xmax)
698                                 to = xmax;
699                         }
700 #endif
701         set_bitmap_bits(scan_line, from, to);
702         }
703     }
704 }
705
706 #endif
707
708 \f
709
710