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