]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/Speedo/out_scrn.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / lib / font / Speedo / out_scrn.c
1 /* $XConsortium: out_scrn.c,v 1.5 94/02/10 14:15:39 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 /*************************** O U T _ S C R N . C *****************************
27  *                                                                           *
28  * This is an output module for screen-writer mode.                          *
29  *                                                                           *
30  *****************************************************************************/
31
32
33 #include "spdo_prv.h"               /* General definitions for Speedo   */
34
35 #define   DEBUG      0
36 #define   LOCAL      static
37 #define   ABS(X)     ( (X < 0) ? -X : X)
38
39 #if DEBUG
40 #include <stdio.h>
41 #define SHOW(X) printf("X = %d\n", X)
42 #else
43 #define SHOW(X)
44 #endif
45
46
47 /***** GLOBAL VARIABLES *****/
48
49 /***** GLOBAL FUNCTIONS *****/
50
51 /***** EXTERNAL VARIABLES *****/
52
53 /***** EXTERNAL FUNCTIONS *****/
54
55 /***** STATIC VARIABLES *****/
56
57 /***** STATIC FUNCTIONS *****/
58
59 #if PROTOS_AVAIL
60 static void sp_add_intercept_screen(PROTO_DECL2 fix15 y,fix31 x);
61 static void sp_proc_intercepts_screen(PROTO_DECL1);
62 #else
63 static void    sp_add_intercept_screen();
64 static void    sp_proc_intercepts_screen();
65 #endif
66
67 \f
68 #if INCL_SCREEN
69 FUNCTION boolean init_screen(specsarg)
70 GDECL
71 specs_t FONTFAR *specsarg;
72 /*
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.
76  */
77 {
78 #if DEBUG
79 printf("INIT_SCREEN()\n");
80 #endif
81 return (TRUE);
82 }
83 #endif
84
85
86 #if INCL_SCREEN
87 FUNCTION boolean begin_char_screen(Psw, Pmin, Pmax)
88 GDECL
89 point_t Psw;                   
90 point_t Pmin;                   
91 point_t Pmax;                   
92 /* Called once at the start of the character generation process
93  */
94 {
95 #if DEBUG
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);
100 #endif
101 if (sp_globals.pixshift > 8)
102         sp_intercepts.fracpix = sp_globals.onepix << (8 - sp_globals.pixshift);
103 else
104         sp_intercepts.fracpix = sp_globals.onepix >> (sp_globals.pixshift - 8);
105
106 init_char_out(Psw,Pmin,Pmax);
107
108 return TRUE;
109 }
110 #endif
111
112 \f
113 #if INCL_SCREEN
114 FUNCTION void begin_contour_screen(P1, outside)
115 GDECL
116 point_t P1;                   
117 boolean outside;
118 /* Called at the start of each contour
119  */
120 {
121
122 #if DEBUG
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");
125 #endif
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;
129 }
130 #endif
131 \f
132 #if INCL_SCREEN
133 FUNCTION void curve_screen(P1, P2, P3, depth)
134 GDECL
135 point_t P1, P2, P3;
136 fix15 depth;
137 {
138 fix31   X0;
139 fix31   Y0;
140 fix31   X1;
141 fix31   Y1;
142 fix31   X2;
143 fix31   Y2;
144 fix31   X3;
145 fix31   Y3;
146 #if DEBUG
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);
151 #endif
152
153
154 if (sp_globals.extents_running) /* Accumulate actual character extents if required */
155     {
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;
164     }
165
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;
174
175 if (((Y0 - Y3) * sp_globals.tcb.mirror) > 0)
176         {
177         sp_intercepts.leftedge = LEFT_INT;
178         }
179 else
180         {
181         sp_intercepts.leftedge = 0;
182         }
183
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 */
188 }
189
190 FUNCTION void scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3)\f
191 GDECL
192 fix31 X0,Y0,X1,Y1,X2,Y2,X3,Y3;
193 /* Called for each curve in the transformed character if curves out enabled
194  */
195 {
196 fix31 Pmidx;
197 fix31 Pmidy;
198 fix31 Pctrl1x;
199 fix31 Pctrl1y;
200 fix31 Pctrl2x;
201 fix31 Pctrl2y;
202
203 #if DBGCRV
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);
209 #endif
210
211 if (((Y3 >> 16)) == (Y0 >> 16) || (Y3+1) == Y0 || Y3 == (Y0+1))
212     {
213         return;
214     }
215 if ((X3 >> 16) == (X0 >> 16))
216     {
217     vert_line_screen(X3,(Y0>>16),(Y3>>16));
218         return;
219     }
220 Pmidx = (X0 + (X1 + X2) * 3 + X3 + 4 ) >> 3;
221 Pmidy = (Y0 + (Y1 + Y2) * 3 + Y3 + 4 ) >> 3;
222
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);
228
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);
234 }             
235 \f
236 FUNCTION void vert_line_screen(x,y1,y2)
237 GDECL
238 fix31 x;
239 fix15 y1, y2;
240 {                                                 
241
242 #if DBGCRV
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);
247 #endif
248
249 if (sp_globals.intercept_oflo) 
250     return;
251
252 if (y1 > y2)                                   /* Line goes downwards ? */
253         {
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 */
258
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 */
261
262         while (y2 < y1)                            /* At least one intercept left? */
263                 {
264                 sp_add_intercept_screen(--y1, x);           /* Add intercept */
265                 }
266         }
267 else if (y2 > y1)                              /* Line goes upwards ? */
268         {
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 */
273
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 */
276
277         while (y1 < y2)                            /* At least one intercept left? */
278                 {
279                 sp_add_intercept_screen(y1++, x);           /* Add intercept */
280                 }
281         }
282
283
284 }
285         
286 #endif
287 \f
288
289 #if INCL_SCREEN
290 FUNCTION void line_screen(P1)
291 GDECL
292 point_t P1;                   
293 /* Called for each vector in the transformed character
294  */
295 {
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 */
303
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) */
308
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 */
311
312
313 #if DEBUG
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);
317 #endif
318
319 if (sp_globals.extents_running)
320     {
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;
329     }
330
331 if (sp_globals.intercept_oflo) return;
332
333 if ((how_many_y = sp_globals.y_pxl - yc) == 0) return; /* Don't draw a null line */
334
335 xc = (fix31)(x0 + sp_globals.pixrnd) << (16 - sp_globals.pixshift); /* Original x coordinate with built in  */
336                                             /* rounding. 16.16 form */
337
338 if (how_many_y < 0)
339         {
340         yc--; /* Predecrment downward lines */
341         }
342
343 if ((how_many_y * sp_globals.tcb.mirror) < 0)
344         {
345         sp_intercepts.leftedge = LEFT_INT;
346         }
347 else
348         {
349         sp_intercepts.leftedge = 0;
350         }
351
352 if (yc > sp_globals.y_band.band_max) /* Is start point above band? */
353     {
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 */
356     }
357
358 if (yc < sp_globals.y_band.band_min)   /* Is start point below band? */
359     {
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 */
362     }
363
364 if ( (temp1 = (x1 - x0)) == 0)  /* check for vertical line */
365     {
366     dx_dy = 0L; /* Zero slope, leave xc alone */
367     goto skip_calc;
368     }
369           
370 /* calculate dx_dy at 16.16 fixed point */
371
372 dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
373
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.                              */
379
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       */
383
384 temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
385
386 if (  (temp2 != (fix15)-1) &&
387       (temp2 != 0x0000)   )
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);
392         }
393     goto skip_calc;
394     }
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 */
400
401 xc += ((fix31)temp1 * dx_dy) >> sp_globals.pixshift;
402
403 skip_calc:
404
405 yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
406
407 if (how_many_y < 0)
408     {   /* Vector down */
409     if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
410     while(yc >= how_many_y)
411         {
412         sp_add_intercept_screen(yc--,xc); 
413         xc -= dx_dy;
414         }
415     }
416     else
417     {   /* Vector up */
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)
421         {
422         sp_add_intercept_screen(yc++,xc); 
423         xc += dx_dy;
424         }
425     }
426 }
427 #endif
428 \f
429 #if INCL_SCREEN
430 FUNCTION void end_contour_screen()
431 GDECL
432 /* Called after the last vector in each contour
433  */
434 {
435 #if DEBUG
436 printf("END_CONTOUR_SCREEN()\n");
437 #endif
438 sp_intercepts.inttype[sp_globals.next_offset-1] |= END_INT;
439 }
440 #endif
441
442
443 \f
444 #if INCL_SCREEN
445 FUNCTION boolean end_char_screen()
446 GDECL
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
451  */
452 {
453
454 fix31 xorg;
455 fix31 yorg;
456
457 #if INCL_CLIPPING
458 fix31 em_max, em_min, bmap_max, bmap_min;
459 #endif
460
461 #if DEBUG
462 printf("END_CHAR_SCREEN()\n");
463 #endif
464
465 if (sp_globals.first_pass)
466     {
467     if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
468         {
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;
471         }
472     else
473         {
474         sp_globals.xmin = sp_globals.xmax = 0;
475         }
476     if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
477         {
478
479 #if INCL_CLIPPING
480     switch(sp_globals.tcb0.xtype)
481        {
482        case 1: /* 180 degree rotation */
483             if (sp_globals.specs.flags & CLIP_TOP)
484                {
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;
491                else
492                     sp_globals.ymin = bmap_min;
493                }
494             if (sp_globals.specs.flags & CLIP_BOTTOM)
495                {
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;
501                else
502                     sp_globals.ymax = sp_globals.clip_ymax;
503                }
504                sp_globals.clip_xmax =  -sp_globals.xmin;
505                sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
506                                       sp_globals.xmin;
507                break;
508        case 2: /* 90 degree rotation */
509             if (sp_globals.specs.flags & CLIP_TOP)
510                {
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;
517
518                /* normalize to x origin */
519                sp_globals.clip_xmin -= sp_globals.xmin;
520                }
521             if (sp_globals.specs.flags & CLIP_BOTTOM)
522                {
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;
528                else
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;
540                }
541                break;
542        case 3: /* 270 degree rotation */
543             if (sp_globals.specs.flags & CLIP_TOP)
544                {
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;
549
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;
553
554                /* normalize the x value to new xorgin */
555                sp_globals.clip_xmin -= sp_globals.xmin;
556                }
557             if (sp_globals.specs.flags & CLIP_BOTTOM)
558                {
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;
562
563                /* let the max be the lesser of these two values */
564                if (bmap_max < sp_globals.clip_xmax)
565                     {
566                     sp_globals.xmax = bmap_max; 
567                     sp_globals.clip_xmax = bmap_max;
568                     }
569                else
570                     sp_globals.xmax = sp_globals.clip_xmax;
571
572                /* normalize the x value to new x origin */
573                sp_globals.clip_xmax -= sp_globals.xmin;
574                }
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;
584                break;
585        default: /* this is for zero degree rotation and arbitrary rotation */
586             if (sp_globals.specs.flags & CLIP_TOP)
587                {
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;
593                else
594                     sp_globals.ymax = sp_globals.clip_ymax;
595                }
596             if (sp_globals.specs.flags & CLIP_BOTTOM)
597                {
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;
604                else
605                     sp_globals.ymin = bmap_min;
606                }
607                sp_globals.clip_xmin = -sp_globals.xmin;
608                sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
609                                       sp_globals.xmin;
610                break;
611        }
612 if ( !(sp_globals.specs.flags & CLIP_TOP))
613 #endif
614             sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
615
616 #if INCL_CLIPPING
617 if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
618 #endif
619
620         sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
621         }
622     else
623         {
624         sp_globals.ymin = sp_globals.ymax = 0;
625         }
626
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));
630     else
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)) ;
633         else
634                 xorg = (fix31)sp_globals.xmin << 16;   /* for other cases don't use round on x */
635            
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));
638     else
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;
643
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)
647         {
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;
653         return FALSE;
654         }
655     else
656         {
657         sp_proc_intercepts_screen();
658         close_bitmap();
659         return TRUE;
660         }
661     }
662 else
663     {
664     if (sp_globals.intercept_oflo)
665         {
666         reduce_band_size_out();
667         init_intercepts_out();
668         return FALSE;
669         }
670     else
671         {
672         sp_proc_intercepts_screen();
673         if (next_band_out())
674             {
675             init_intercepts_out();
676             return FALSE;
677             }
678         close_bitmap();
679         return TRUE;
680         }
681     }
682 }
683 #endif
684 \f
685 #if INCL_SCREEN
686 FUNCTION LOCAL  void sp_add_intercept_screen(y, x)
687 GDECL
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 */
691
692 /*  Called by line() to add an intercept to the intercept list structure
693  */
694
695 {
696 register fix15 from;   /* Insertion pointers for the linked list sort */
697 register fix15 to;
698 register fix15 xloc;
699 register fix15 xfrac;
700
701 #if DEBUG
702 printf("    Add intercept(%2d, %x)\n", y + sp_globals.y_band.band_min, x);
703
704 /* Bounds checking IS done in debug mode */
705 if (y < 0)       /* Y value below bottom of current band? */
706     {
707     printf(" Intecerpt less than 0!!!\007\n");
708     return;
709     }
710
711 if (y > (sp_globals.no_y_lists - 1))              /* Y value above top of current band? */
712     {
713     printf(" Intercept too big for band!!!!!\007\n");
714     return;
715     }
716 #endif
717
718 /* Store new values */
719
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));
722
723 /* Find slot to insert new element (between from and to) */
724
725 from = y; /* Start at list head */
726
727 while( (to = sp_intercepts.cdr[from]) != 0) /* Until to == end of list */
728     {
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 */
734     }
735
736 insert_element: /* insert element "sp_globals.next_offset" between elements "from" */
737                 /* and "to" */
738
739 sp_intercepts.cdr[from] = sp_globals.next_offset;
740 sp_intercepts.cdr[sp_globals.next_offset] = to;
741
742 if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
743     {
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;
749     }
750 }
751
752 #endif
753 \f
754 #if INCL_SCREEN
755 FUNCTION LOCAL  void sp_proc_intercepts_screen()
756 GDECL
757
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
760  */
761 {
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  */
766 register fix15 y;
767 register fix15 scan_line;
768          fix15 first_y, last_y;
769          fix15 xsave;
770          fix15 xmin, xmax;
771          boolean clipleft, clipright;
772
773
774 fix15 diff;
775
776 #if DEBUG
777 printf("\nPROC_INTERCEPTS_SCREEN: Intercept lists before:\n");
778 #endif
779
780 #if INCL_CLIPPING
781 if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
782     clipleft = TRUE;
783 else
784     clipleft = FALSE;
785 if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
786     clipright = TRUE;
787 else
788     clipright = FALSE;
789 if (clipleft || clipright)
790         {
791         xmax = sp_globals.clip_xmax + sp_globals.xmin;
792         xmin = sp_globals.clip_xmin + sp_globals.xmin;
793         }
794 if (!clipright)
795         xmax = ((sp_globals.set_width.x+32768L) >> 16);
796 #endif
797
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 */
800
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 */
803
804 last_y  -= sp_globals.y_band.band_min;
805
806 #if DEBUG
807 /* Print out all of the intercept info */
808 scan_line = sp_globals.ymax - first_y - 1;
809
810 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
811     {
812     i = y;                            /* Index head of intercept list */
813     while ((i = sp_intercepts.cdr[i]) != 0)         /* Link to next intercept if present */
814         {
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? */
819             {
820             printf("****** proc_intercepts: odd number of intercepts\n");
821             break;
822             }
823         if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
824             to = sp_globals.xmax - sp_globals.xmin;         /* Clip to sp_globals.xmax boundary */
825         else
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);
829         }
830     }
831 #endif
832
833 /* CHECK INTERCEPT LIST FOR DROPOUT AND WINDING, FIX IF NECESSARY  */
834
835 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--)
836     {
837         previ = y;
838     i = sp_intercepts.cdr[y];                            /* Index head of intercept list */
839     while (i  != 0)         /* Link to next intercept if present */
840         {
841                 j = i;
842         i = sp_intercepts.cdr[i];                   /* Link to next intercept */
843                 if (sp_intercepts.inttype[i] & LEFT_INT)
844                         {
845                         if (sp_intercepts.inttype[j] & LEFT_INT)
846                                 {
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;
850                                 }
851                         else
852                                 {
853                                 xsave = sp_intercepts.car[j];
854                                 sp_intercepts.car[j] = sp_intercepts.car[i];
855                                 sp_intercepts.car[i] = xsave;
856
857                                 xsave = sp_intercepts.inttype[j];
858                                 sp_intercepts.inttype[j] = sp_intercepts.inttype[i] & FRACTION;
859                                 sp_intercepts.inttype[i] = xsave | LEFT_INT;
860
861                                 sp_intercepts.cdr[previ] = i;
862                                 sp_intercepts.cdr[j] = sp_intercepts.cdr[i];
863                                 sp_intercepts.cdr[i] = j;
864                                 i = j;
865                                 j = sp_intercepts.cdr[previ];
866                                 }
867                         }
868
869         if (sp_intercepts.car[j] < sp_globals.xmin)
870             sp_intercepts.car[j] = sp_globals.xmin;                 /* Clip to sp_globals.xmin boundary */
871
872         if (sp_intercepts.car[i] > sp_globals.xmax)
873             sp_intercepts.car[i] = sp_globals.xmax;
874
875         if (sp_intercepts.car[j] >= sp_intercepts.car[i])
876                         {
877                         if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i] & FRACTION) > sp_intercepts.fracpix)
878                                 ++sp_intercepts.car[i];
879                         else
880                                 --sp_intercepts.car[j];
881                         }
882                 if (sp_globals.first_pass)
883                         {
884                         if (sp_intercepts.inttype[i-1] & END_INT)
885                                 {
886                                 for (iminus1 = i+1; !(sp_intercepts.inttype[iminus1] & END_INT); iminus1++)
887                                         ;
888                                 }
889                         else
890                                 iminus1 = i-1;
891         
892                         if (sp_intercepts.inttype[j] & END_INT)
893                                 {
894                                 for (jplus1 = j-1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1--)
895                                         ;
896                                 jplus1++;
897                                 }
898                         else
899                                 jplus1 = j+1;
900
901                         if ((sp_intercepts.inttype[iminus1] & LEFT_INT)) 
902                                 {
903                                 if ( sp_intercepts.car[jplus1] > sp_intercepts.car[i])
904                                         {
905                                         diff = sp_intercepts.car[jplus1] - sp_intercepts.car[i];
906                                         sp_intercepts.car[i] += diff/2;
907                         sp_intercepts.car[jplus1] -= diff/2;
908                                         if (diff & 1)
909                                                 {
910                                                 if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) > sp_intercepts.fracpix)
911                                                         sp_intercepts.car[i] ++;
912                                                 else
913                                                         sp_intercepts.car[jplus1]--;
914                                                 }
915                                         }
916                                 }
917                         else if (!(sp_intercepts.inttype[jplus1] & LEFT_INT))
918                                 {
919                                 if (sp_intercepts.car[iminus1] < sp_intercepts.car[j])
920                                         {
921                                         diff = sp_intercepts.car[j] - sp_intercepts.car[iminus1];
922                                         sp_intercepts.car[j] -= diff/2;
923                         sp_intercepts.car[iminus1] += diff/2;
924                                         if (diff & 1)
925                                                 {
926                                                 if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + 
927                                                (ufix16)(sp_intercepts.inttype[iminus1] & FRACTION) > sp_intercepts.fracpix)
928                                                         sp_intercepts.car[iminus1]++;
929                                                 else
930                                                         sp_intercepts.car[j]--;
931                                                 }
932                                         }
933                                 }
934                         if (sp_globals.tcb.mirror == -1) 
935                                 {
936                                 if (sp_intercepts.inttype[j-1] & END_INT)
937                                         {
938                                         for (jplus1 = j+1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1++)
939                                                 ;
940                                         }
941                                 else
942                                         {
943                                         jplus1 = j-1;
944                                         }
945                                 }
946
947                         if (!(sp_intercepts.inttype[jplus1] & LEFT_INT) && 
948                            sp_intercepts.car[j] > sp_intercepts.car[jplus1])
949                                 {
950                                 k = sp_intercepts.cdr[y - 1];
951                                 while (k > 0)
952                                         {
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])
957                                                 {
958                                                 if ((diff=sp_intercepts.car[j] - sp_intercepts.car[k]) > 0)
959                                                         {
960                                                         if (diff <= (sp_intercepts.car[nextk] - sp_intercepts.car[jplus1]))
961                                                                 {
962                                                                 sp_intercepts.car[j] -= diff/2;
963                                             sp_intercepts.car[k] += diff/2;
964                                                                 if (diff & 1)
965                                                                         {
966                                                                         if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + 
967                                                        (ufix16)(sp_intercepts.inttype[k] & FRACTION) > sp_intercepts.fracpix)
968                                                                                 sp_intercepts.car[j]--;
969                                                                         else
970                                                                                 sp_intercepts.car[k]++;
971                                                                         }
972                                                                 }
973                                                         else
974                                                                 {
975                                                                 diff = sp_intercepts.car[nextk] - sp_intercepts.car[jplus1];
976                                                                 sp_intercepts.car[nextk] -= diff/2;
977                                             sp_intercepts.car[jplus1] += diff/2;
978                                                                 if (diff & 1)
979                                                                         {
980                                                                         if ((ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) + 
981                                                        (ufix16)(sp_intercepts.inttype[nextk] & FRACTION) > sp_intercepts.fracpix)
982                                                                                 sp_intercepts.car[nextk]--;
983                                                                         else
984                                                                                 sp_intercepts.car[jplus1]++;
985                                                                         }
986                                                                 }
987                                                         }
988                                                 break;
989                                                 }
990                                         k = nextk;
991                                         }
992                                 }
993                         if (j > 0 && sp_intercepts.car[j-1] > sp_intercepts.car[i] && !(sp_intercepts.inttype[j-1] & END_INT))
994                                 {
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;
998                                 if (diff & 1)
999                                         {
1000                                         if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[j-1] & FRACTION) > sp_intercepts.fracpix)
1001                                                 sp_intercepts.car[i]++;
1002                                         else
1003                                                 sp_intercepts.car[j-1]--;
1004                                         }
1005                                 }
1006                         if (sp_intercepts.car[i+1] < sp_intercepts.car[j] && !(sp_intercepts.inttype[i] & END_INT))
1007                                 {
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;
1011                                 if (diff & 1)
1012                                         {
1013                                         if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i+1] & FRACTION) > sp_intercepts.fracpix)
1014                                                 sp_intercepts.car[i+1]++;
1015                                         else
1016                                                 sp_intercepts.car[j]--;
1017                                         }
1018         
1019                                 }
1020                         previ = i;
1021                 }
1022                 i = sp_intercepts.cdr[i];
1023             }
1024         }
1025
1026 #if DEBUG
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;
1030
1031 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
1032     {
1033     i = y;                            /* Index head of intercept list */
1034     while ((i = sp_intercepts.cdr[i]) != 0)         /* Link to next intercept if present */
1035         {
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? */
1040             {
1041             printf("****** proc_intercepts: odd number of intercepts\n");
1042             break;
1043             }
1044         if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
1045             to = sp_globals.xmax - sp_globals.xmin;         /* Clip to sp_globals.xmax boundary */
1046         else
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);
1050         }
1051     }
1052 #endif                                                            
1053
1054 /*  INTERCEPTS ALL PATCHED, NOW DRAW THE IMAGE */
1055 scan_line = sp_globals.ymax - first_y - 1;
1056
1057 for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
1058     {
1059     i = sp_intercepts.cdr[y];                            /* Index head of intercept list */
1060     while (i  != 0)         /* Link to next intercept if present */
1061         {
1062         from = sp_intercepts.car[i];
1063         i = sp_intercepts.cdr[i];                   /* Link to next intercept */
1064         to = sp_intercepts.car[i];
1065 #if INCL_CLIPPING
1066         if (clipleft)
1067                         {
1068                         if (to <= xmin)
1069                                 {
1070                                 i = sp_intercepts.cdr[i];
1071                                 continue;
1072                                 }
1073                         if (from < xmin)
1074                                 from = xmin;
1075                         }
1076         if (clipright)
1077                         {
1078                         if (from >= xmax)
1079                                 {
1080                                 i = sp_intercepts.cdr[i];
1081                                 continue;
1082                                 }
1083                         if (to > xmax)
1084                                 to = xmax;
1085                         }
1086 #endif
1087         set_bitmap_bits(scan_line, from-sp_globals.xmin, to-sp_globals.xmin);
1088         i = sp_intercepts.cdr[i];
1089         }
1090     }
1091 }
1092
1093 #endif