home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / lib / ttraster.c < prev    next >
C/C++ Source or Header  |  1997-10-06  |  76KB  |  2,388 lines

  1. /*******************************************************************
  2.  *
  3.  *  ttraster.c                                                  1.4
  4.  *
  5.  *  The FreeType glyph rasterizer (body).
  6.  *
  7.  *  Copyright 1996, 1997 by
  8.  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  9.  *
  10.  *  This file is part of the FreeType project, and may only be used
  11.  *  modified and distributed under the terms of the FreeType project
  12.  *  license, LICENSE.TXT. By continuing to use, modify or distribute
  13.  *  this file you indicate that you have read the license and
  14.  *  understand and accept it fully.
  15.  *
  16.  *  NOTES:
  17.  *
  18.  *  This version supports the following:
  19.  *
  20.  *    - direct grayscaling
  21.  *    - sub-banding
  22.  *    - drop-out modes 4 and 5
  23.  *    - second pass for complete drop-out control (bitmap only)
  24.  *    - variable precision
  25.  *
  26.  *
  27.  *   Changes between 1.4 and 1.3:
  28.  *
  29.  *   Mainly performance tunings :
  30.  *
  31.  *   - Line_Down and Bezier_Down now use the functions Line_Up
  32.  *     and Bezier_Up to do their work.
  33.  *   - optimized Split_Bezier
  34.  *   - optimized linked lists used during sweeps
  35.  *
  36.  *   Changes between 1.2 and 1.3:
  37.  *
  38.  *     - made the engine optionaly re-entrant. Saves a lot
  39.  *       of code for a moderate performance hit.
  40.  *
  41.  ******************************************************************/
  42.  
  43. #include "ttraster.h"
  44. #include "tterror.h"
  45. #include "tttypes.h"
  46. #include "ttengine.h"
  47.  
  48. #include "ttmemory.h"
  49.  
  50. #define  RASTER_RENDER_POOL   64000
  51. /* The default render pool size */
  52.  
  53. #define  RASTER_GRAY_LINES    2048
  54. /* The size of the two-lines intermediate bitmap used */
  55. /* for anti-aliasing                                  */
  56.  
  57. #define Raster_Err_None              TT_Err_Ok
  58. #define Raster_Err_Not_Ini           TT_Err_Raster_Not_Initialized
  59. #define Raster_Err_Overflow          TT_Err_Raster_Pool_Overflow
  60. #define Raster_Err_Neg_Height        TT_Err_Raster_Negative_Height
  61. #define Raster_Err_Invalid           TT_Err_Raster_Invalid_Value
  62. #define Raster_Err_Gray_Unsupported  TT_Err_Raster_Gray_Unsupported
  63.  
  64. /* Bug fixes :                                                            */
  65. /*                                                                        */
  66. /*   11/16/96 : David : Added first grayscale support.                    */
  67. /*   11/ 8/96 : David : Fixed 'Curve_To' from access bug                  */
  68. /*   03/10/97 : David : Synchronized to Pascal version                    */
  69. /*   03/13/97 : David : bug fix in gray rendering                         */
  70.  
  71. /* Define this if you want to use the 'MulDiv' function from 'ttcalc'.    */
  72. /* (it computes (A*B)/C with 64 bits intermediate accuracy. However, for  */
  73. /* 99.9% of screen display, this operation can be done directly with      */
  74. /* good accuracy, because 'B' is only a 6bit integer).                    */
  75. /*                                                                        */
  76. /* Note that some compilers can manage directly 'a*b/c' with intermediate */
  77. /* accuracy (GCC can use long longs, for example). Using the unsecure     */
  78. /* definition of MulDiv would then be sufficient.                         */
  79. /*                                                                        */
  80. /* The SECURE_COMPUTATIONS option is probably a good option for 16 bits   */
  81. /*  compilers.                                                            */
  82.  
  83. #ifdef SECURE_COMPUTATIONS
  84.   #include "ttcalc.h"
  85. #else
  86.   #define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
  87. #endif
  88.  
  89. /* Define DEBUG_RASTER if you want to generate a debug version of the  */
  90. /* rasterizer. This will progressively draw the glyphs while all the   */
  91. /* computation are done directly on the graphics screen (the glyphs    */
  92. /* will be inverted).                                                  */
  93.  
  94. /* Note that DEBUG_RASTER should only be used for debugging with b/w   */
  95. /* rendering, not with gray levels.                                    */
  96.  
  97. /* The definition of DEBUG_RASTER should appear in the file "ttconfig.h". */
  98.  
  99. #ifdef DEBUG_RASTER
  100.   extern char*  Vio;  /* A pointer to VRAM or display buffer */
  101. #endif
  102.  
  103. /* The rasterizer is a very general purpose component, please leave */
  104. /* the following redefinitions there (you never know your target    */
  105. /* environment).                                                    */
  106.  
  107. #ifndef TRUE
  108. #define TRUE   1
  109. #endif
  110.  
  111. #ifndef FALSE
  112. #define FALSE  0
  113. #endif
  114.  
  115. #ifndef NULL
  116. #define NULL  (void*)0
  117. #endif
  118.  
  119. #define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
  120.                         /* Setting this constant to more than 32 is a   */
  121.                         /* pure waste of space.                         */
  122.  
  123. #define Pixel_Bits  6   /* fractional bits of input coordinates */
  124.  
  125.   /* States of each line, arc and profile */
  126.   typedef enum _TStates
  127.   {
  128.     Unknown,
  129.     Ascending,
  130.     Descending,
  131.     Flat
  132.   } TStates;
  133.  
  134.   struct _TProfile;
  135.   typedef struct _TProfile  TProfile;
  136.   typedef TProfile*         PProfile;
  137.  
  138.   struct _TProfile
  139.   {                                                                     
  140.     Int         flow;        /* Profile orientation: Asc/Descending      */
  141.     Int         height;      /* profile's height in scanlines            */
  142.     Int         start;       /* profile's starting scanline              */
  143.     PStorage    offset;      /* start of profile's data in render pool   */
  144.  
  145.     PProfile    link;        /* link to next profile                     */
  146.  
  147.     TT_F26Dot6  X;           /* current coordinate during sweep          */
  148.     Int         countL;      /* number of lines to step before this      */
  149.                              /* profile becomes drawable                 */
  150.  
  151.     PProfile    next;        /* next profile in same contour, used       */
  152.                              /* during drop-out control                  */
  153.   };
  154.  
  155.   typedef PProfile  TProfileList;
  156.   typedef PProfile* PProfileList;
  157.  
  158.   /* I use the classic trick of two dummy records for the head and tail  */
  159.   /* of a linked list, this reduces tests in insertion/deletion/sorting. */
  160.   /* NOTE: used during sweeps only.                                      */
  161.  
  162.   /* Simple record used to implement a stack of bands, required */
  163.   /* by the sub-banding mechanism                               */
  164.   typedef struct _TBand
  165.   {
  166.     Int  y_min;   /* band's minimum */
  167.     Int  y_max;   /* band's maximum */
  168.   } TBand;
  169.  
  170. #define AlignProfileSize  ( (sizeof ( TProfile ) + 7) / 4)
  171.  
  172.   /* Left fill bitmask */
  173.   static const unsigned char  LMask[8] = 
  174.     { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
  175.  
  176.   /* Right fill bitmask */
  177.   static const unsigned char  RMask[8] =
  178.     { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
  179.  
  180.   /* prototypes used for sweep function dispatch */
  181.   typedef void  Function_Sweep_Init( RAS_ARGS  int*  min, int*  max );
  182.  
  183.   typedef void  Function_Sweep_Span( RAS_ARGS  int         y,
  184.                                                TT_F26Dot6  x1,
  185.                                                TT_F26Dot6  x2,
  186.                                                PProfile    left,
  187.                                                PProfile    right );
  188.                     
  189.   typedef void  Function_Sweep_Step( RAS_ARG );
  190.  
  191.  
  192. /* NOTE : These operations are only valid on 2's complement processors */
  193. #define FLOOR( x )    ( (x) & -ras.precision )
  194. #define CEILING( x )  ( ((x) + ras.precision-1) & -ras.precision )
  195. #define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
  196. #define FRAC( x )     ( (x) & (ras.precision - 1) )
  197. #define SCALED( x )   ( (x) << ras.precision_shift )
  198.  
  199. #ifdef DEBUG_RASTER
  200. #define DEBUG_PSET  Pset()
  201. #else
  202. #define DEBUG_PSET  
  203. #endif
  204.  
  205.   typedef struct _TPoint
  206.   {
  207.     Long  x, y;
  208.   } TPoint;
  209.  
  210.   /* Note that I have moved the location of some fields in the */
  211.   /* structure, this to ensure that the mostly used variables  */
  212.   /* are used at the top. Thus, their offset can be coded with */
  213.   /* less opcodes, and it results in a smaller executable      */
  214.  
  215.   struct _TRaster_Instance
  216.   {
  217.     Int       precision_bits;   /* precision related variables */
  218.     Int       precision;
  219.     Int       precision_half;
  220.     Long      precision_mask;
  221.     Int       precision_shift;
  222.     Int       precision_step;
  223.  
  224.     PStorage  buff;                   /* The profiles buffer          */
  225.     PStorage  maxBuff;                /* Profiles buffer size         */
  226.     PStorage  top;                    /* Current cursor in buffer     */
  227.  
  228.     Int  error;
  229.  
  230.     PByte     flags;   /* current flags table    */
  231.     PUShort   outs;    /* current outlines table */
  232.    
  233.     Int       nPoints;   /* number of points in current glyph   */
  234.     Int       nContours; /* number of contours in current glyph */
  235.    
  236.     TPoint*   arc;         /* current Bezier arc pointer */
  237.    
  238.     Int       bWidth;  /* target bitmap width  */
  239.     PByte     bTarget; /* target bitmap buffer */
  240.     PByte     gTarget; /* target pixmap buffer */
  241.    
  242.     Long      lastX, lastY, minY, maxY;
  243.    
  244.     Int       num_Profs;  /* current number of profiles */
  245.    
  246.     Bool      fresh;    /* signals a fresh new profile which 'start'*/ 
  247.                         /* field must be completed                  */
  248.    
  249.     Bool      joint;    /* signals that le last arc ended exactly   */
  250.                         /* on a scanline. Allows removal of doublets*/
  251.    
  252.     PProfile  cProfile; /* current profile                           */
  253.     PProfile  fProfile; /* head of linked list of profiles           */
  254.     PProfile  gProfile; /* contour's first profile in case of impact */
  255.    
  256.     TStates   state;    /* rendering state */
  257.    
  258.     TT_Raster_Map  target;  /* description of target bit/pixmap */
  259.    
  260.     Int       traceOfs;    /* current offset in target bitmap */
  261.     Int       traceG;      /* current offset in target pixmap */
  262.    
  263.     Int       traceIncr;   /* sweep's increment in target bitmap      */
  264.    
  265.     Int       gray_min_x;  /* current min x during gray rendering */
  266.     Int       gray_max_x;  /* current max x during gray rendering */
  267.    
  268.     /* dispatch variables */
  269.    
  270.     Function_Sweep_Init*  Proc_Sweep_Init;
  271.     Function_Sweep_Span*  Proc_Sweep_Span;
  272.     Function_Sweep_Span*  Proc_Sweep_Drop;
  273.     Function_Sweep_Step*  Proc_Sweep_Step;
  274.    
  275.     PStorage  x_coord;  /* current ras.x_coord table */
  276.     PStorage  y_coord;  /* current ras.y_coord table */
  277.    
  278.     Byte      dropOutControl;   /* current drop_out control method */
  279.    
  280.     char      grays[5]; /* Palette of gray levels used for render */
  281.    
  282.     Byte*     gray_lines; /* Intermediate table used to render the  */
  283.                           /* graylevels pixmaps                     */
  284.                           /* gray_lines is a buffer holding two     */
  285.                           /* monochrome scanlines                   */
  286.    
  287.     Int       gray_width; /* width in bytes of one monochrome       */
  288.                           /* intermediate scanline of gray_lines.   */
  289.                           /* Each gray pixel takes 2 bits long there*/
  290.    
  291.                 /* The gray_lines must hold 2 lines, thus with size */
  292.                 /* in bytes of at least 'gray_width*2'              */
  293.    
  294.     Bool      second_pass; /* indicates wether a horizontal pass      */
  295.                            /* should be performed to control drop-out */
  296.                            /* accurately when calling Render_Glyph.   */
  297.                            /* Note that there is no horizontal pass   */
  298.                            /* during gray rendering.                  */
  299.    
  300.     TPoint    arcs[ 2*MaxBezier+1 ];    /* The Bezier stack */
  301.    
  302.     TBand     band_stack[16];  /* band stack used for sub-banding */
  303.     Int       band_top;        /* band stack top                  */
  304.    
  305.     Int       count_table[256]; /* Look-up table used to quickly count */
  306.                                 /* set bits in a gray 2x2 cell         */
  307.    
  308.   };
  309.  
  310. #ifdef TT_STATIC_RASTER
  311.  
  312.   static TRaster_Instance  cur_ras;
  313.   #define ras  cur_ras
  314.  
  315. #else
  316.  
  317.   #define ras  (*raster)
  318.  
  319. #endif /* TT_STATIC_RASTER */
  320.  
  321.  
  322. #ifdef DEBUG_RASTER
  323.  
  324.   /************************************************/
  325.   /*                                              */
  326.   /* Pset :                                       */
  327.   /*                                              */
  328.   /*  Used for debugging only. Plots a point      */
  329.   /*  in VRAM during rendering (not afterwards).  */
  330.   /*                                              */
  331.   /* NOTE : This procedure relies on the value    */
  332.   /*        of cProfile->start, which may not     */
  333.   /*        be set when Pset is called sometimes  */
  334.   /*        This will usually result in a dot     */
  335.   /*        plotted on the first screen scanline  */
  336.   /*        (far away its original position).     */
  337.   /*                                              */
  338.   /*        This "bug" reflects nothing wrong     */
  339.   /*        in the current implementation, and    */
  340.   /*        the bitmap is rendered correctly,     */
  341.   /*        so don't panic if you see 'flying'    */
  342.   /*        dots in debugging mode.               */
  343.   /*                                              */
  344.   /*  - David                                     */
  345.   /*                                              */
  346.   /************************************************/
  347.  
  348.   static void  Pset( RAS_ARG )
  349.   {
  350.     Long  o;
  351.     Long  x;
  352.  
  353.     x = ras.top[-1];
  354.  
  355.     switch ( ras.cProfile->flow )
  356.     {
  357.     case TT_Flow_Up:
  358.       o = Vio_ScanLineWidth *
  359.          ( ras.top-ras.cProfile->offset + ras.cProfile->start ) +
  360.          ( x / (ras.precision*8) );
  361.       break;
  362.  
  363.     case TT_Flow_Down:
  364.       o = Vio_ScanLineWidth *
  365.          ( ras.cProfile->start-ras.top + ras.cProfile->offset ) +
  366.          ( x / (ras.precision*8) );
  367.       break;
  368.     }
  369.  
  370.     if ( o > 0 )
  371.       Vio[o] |= (unsigned)0x80 >> ( (x/ras.precision) & 7 );
  372.   }
  373.  
  374.  
  375.   static void  Clear_Band( RAS_ARGS  Int  y1, Int  y2 )
  376.   {
  377.     MEM_Set( Vio + y1*Vio_ScanLineWidth, (y2-y1+1)*Vio_ScanLineWidth, 0 );
  378.   }
  379.  
  380. #endif /* DEBUG_RASTER */
  381.  
  382.  
  383.   /************************************************************************/
  384.   /*                                                                      */
  385.   /* Function:    Set_High_Precision                                      */
  386.   /*                                                                      */
  387.   /* Description: Sets precision variables according to param flag        */
  388.   /*                                                                      */
  389.   /* Input:       High     set to True for high precision (typically for  */
  390.   /*                       ppem < 18), false otherwise.                   */
  391.   /*                                                                      */
  392.   /************************************************************************/
  393.  
  394.   void  Set_High_Precision( RAS_ARGS  int  High )
  395.   {
  396.     if ( High )
  397.     {
  398.       ras.precision_bits = 10;
  399.       ras.precision_step = 128;
  400.     }
  401.     else
  402.     {
  403.       ras.precision_bits = 6;
  404.       ras.precision_step = 32;
  405.     }
  406.  
  407.     ras.precision       = 1 << ras.precision_bits;
  408.     ras.precision_half  = ras.precision / 2;
  409.     ras.precision_shift = ras.precision_bits - Pixel_Bits;
  410.     ras.precision_mask  = -ras.precision;
  411.   }
  412.  
  413.   /************************************************************************/
  414.   /*                                                                      */
  415.   /* Function:    Set_Second_Pass                                         */
  416.   /*                                                                      */
  417.   /* Description: Sets second_pass variable to a given state              */
  418.   /*                                                                      */
  419.   /* Input:       pass     set to True for enabling horizontal drop       */
  420.   /*                       out control. Only vertical control will be     */
  421.   /*                       performed otherwise                            */
  422.   /*                                                                      */
  423.   /************************************************************************/
  424.  
  425.   void Set_Second_Pass( RAS_ARGS  int  pass )
  426.   {
  427.     ras.second_pass = pass;
  428.   }
  429.  
  430. /****************************************************************************/
  431. /*                                                                          */
  432. /* Function:    New_Profile                                                 */
  433. /*                                                                          */
  434. /* Description: Creates a new Profile in the render pool                    */
  435. /*                                                                          */
  436. /* Input:       aState   state/orientation of the new Profile               */
  437. /*                                                                          */
  438. /* Returns:     SUCCESS on success.                                         */
  439. /*              FAILURE in case of overflow or of incoherent Profile.       */
  440. /*                                                                          */
  441. /****************************************************************************/
  442.  
  443.   static Bool  New_Profile( RAS_ARGS  TStates  aState )
  444.   {
  445.     if ( !ras.fProfile )
  446.     {
  447.       ras.cProfile  = (PProfile)ras.top;
  448.       ras.fProfile  = ras.cProfile;
  449.       ras.top      += AlignProfileSize;
  450.     }
  451.  
  452.     if ( ras.top >= ras.maxBuff )
  453.     {
  454.       ras.error = Raster_Err_Overflow;
  455.       return FAILURE;
  456.     }
  457.  
  458.     switch ( aState )
  459.     {
  460.     case Ascending:
  461.       ras.cProfile->flow = TT_Flow_Up;
  462.       break;
  463.  
  464.     case Descending:
  465.       ras.cProfile->flow = TT_Flow_Down;
  466.       break;
  467.  
  468.     default:
  469.       ras.error = Raster_Err_Invalid;
  470.       return FAILURE;
  471.     }
  472.  
  473.     ras.cProfile->start  = 0;
  474.     ras.cProfile->height = 0;
  475.     ras.cProfile->offset = ras.top;
  476.     ras.cProfile->link   = (PProfile)0;
  477.     ras.cProfile->next   = (PProfile)0;
  478.  
  479.     if ( !ras.gProfile ) ras.gProfile = ras.cProfile;
  480.  
  481.     ras.state = aState;
  482.     ras.fresh = TRUE;
  483.     ras.joint = FALSE;
  484.  
  485.     return SUCCESS;
  486.   }
  487.  
  488.  
  489. /****************************************************************************/
  490. /*                                                                          */
  491. /* Function:    End_Profile                                                 */
  492. /*                                                                          */
  493. /* Description: Finalizes the current Profile.                              */
  494. /*                                                                          */
  495. /* Input:       None                                                        */
  496. /*                                                                          */
  497. /* Returns:     SUCCESS on success.                                         */
  498. /*              FAILURE in case of overflow or incoherency.                 */
  499. /*                                                                          */
  500. /****************************************************************************/
  501.  
  502.   static Bool  End_Profile( RAS_ARG )
  503.   {
  504.     Int       h;
  505.     PProfile  oldProfile;
  506.  
  507.     h = ras.top - ras.cProfile->offset;
  508.  
  509.     if ( h < 0 )
  510.     {
  511.       ras.error = Raster_Err_Neg_Height;
  512.       return FAILURE;
  513.     }
  514.  
  515.     if ( h > 0 )
  516.     {
  517.       oldProfile           = ras.cProfile;
  518.       ras.cProfile->height = h;
  519.       ras.cProfile         = (PProfile)ras.top;
  520.  
  521.       ras.top             += AlignProfileSize;
  522.  
  523.       ras.cProfile->height = 0;
  524.       ras.cProfile->offset = ras.top;
  525.       oldProfile->next     = ras.cProfile;
  526.       ras.num_Profs++;
  527.     }
  528.  
  529.     if ( ras.top >= ras.maxBuff )
  530.     {
  531.       ras.error = Raster_Err_Overflow;
  532.       return FAILURE;
  533.     }
  534.  
  535.     ras.joint = FALSE;
  536.  
  537.     return SUCCESS;
  538.   }
  539.  
  540.  
  541. /****************************************************************************/
  542. /*                                                                          */
  543. /* Function:    Finalize_Profile_Table                                      */
  544. /*                                                                          */
  545. /* Description: Adjusts all links in the Profiles list                      */
  546. /*                                                                          */
  547. /* Input:       None                                                        */
  548. /*                                                                          */
  549. /* Returns:     None.                                                       */
  550. /*                                                                          */
  551. /****************************************************************************/
  552.  
  553.   static void  Finalize_Profile_Table( RAS_ARG )
  554.   {
  555.     Int       n;
  556.     PProfile  p;
  557.  
  558.     n = ras.num_Profs;
  559.  
  560.     if ( n > 1 )
  561.     {
  562.       p = ras.fProfile;
  563.       while ( n > 1 )
  564.       {
  565.         p->link = (PProfile)( p->offset + p->height );
  566.         p       = p->link;
  567.         n--;
  568.       }
  569.       p->link = NULL;
  570.     }
  571.     else
  572.       ras.fProfile = NULL;
  573.   }
  574.  
  575.  
  576. /****************************************************************************/
  577. /*                                                                          */
  578. /* Function:    Split_Bezier                                                */
  579. /*                                                                          */
  580. /* Description: Subdivides one Bezier arc into two joint                    */
  581. /*              sub-arcs in the Bezier stack.                               */
  582. /*                                                                          */
  583. /* Input:       None (subdivided bezier is taken from the top of the        */
  584. /*              stack)                                                      */
  585. /*                                                                          */
  586. /* Returns:     None.                                                       */
  587. /*                                                                          */
  588. /*                                                                          */
  589. /* Note : This routine is the 'beef' of this component. It is _the_         */
  590. /*        inner loop that should be optimised to hell to get the            */
  591. /*         best performance                                                 */
  592. /*                                                                          */
  593. /****************************************************************************/
  594.  
  595.   static void  Split_Bezier( TPoint* base )
  596.   {
  597.     Long     a, b;
  598.  
  599.     base[4].x = base[2].x;
  600.     b = base[1].x;
  601.     a = base[3].x = ( base[2].x + b )/2;
  602.     b = base[1].x = ( base[0].x + b )/2;
  603.     base[2].x = (a+b)/2;
  604.  
  605.     base[4].y = base[2].y;
  606.     b = base[1].y;
  607.     a = base[3].y = ( base[2].y + b )/2;
  608.     b = base[1].y = ( base[0].y + b )/2;
  609.     base[2].y = (a+b)/2;
  610.  
  611.     /* hand optimised. gcc doesn't seem too good at common expression  */
  612.     /* substitution and instruction scheduling ;-)                     */
  613.  
  614.     /* On my machine, arial.ttf went from 1.35 to 1.27 s with these lines */
  615.     /* in timer. Watcom crushes it even further (less than 1.07 s)        */
  616.   }
  617.  
  618.  
  619. /****************************************************************************/
  620. /*                                                                          */
  621. /* Function:    Push_Bezier                                                 */
  622. /*                                                                          */
  623. /* Description: Clears the Bezier stack and pushes a new Arc on top of it.  */
  624. /*                                                                          */
  625. /* Input:       x1,y1 x2,y2 x3,y3  new Bezier arc                           */
  626. /*                                                                          */
  627. /* Returns:     None.                                                       */
  628. /*                                                                          */
  629. /****************************************************************************/
  630.  
  631.   static void  Push_Bezier( RAS_ARGS  Long  x1, Long  y1,
  632.                                       Long  x2, Long  y2,
  633.                                       Long  x3, Long  y3 ) 
  634.   {
  635.     ras.arc      = ras.arcs;
  636.     ras.arc[2].x = x1; ras.arc[2].y = y1;
  637.     ras.arc[1].x = x2; ras.arc[1].y = y2;
  638.     ras.arc[0].x = x3; ras.arc[0].y = y3;
  639.   }
  640.  
  641.  
  642. /****************************************************************************/
  643. /*                                                                          */
  644. /* Function:    Line_Up                                                     */
  645. /*                                                                          */
  646. /* Description: Compute the x-coordinates of an ascending line segment      */
  647. /*              and stores them in the render pool.                         */
  648. /*                                                                          */
  649. /* Input:       x1,y1,x2,y2  Segment start (x1,y1) and end (x2,y2) points   */
  650. /*                                                                          */
  651. /* Returns:     SUCCESS on success.                                         */
  652. /*              FAILURE on Render Pool overflow.                            */
  653. /*                                                                          */
  654. /****************************************************************************/
  655.  
  656.   static Bool  Line_Up( RAS_ARGS  Long  x1, 
  657.                                   Long  y1, 
  658.                                   Long  x2, 
  659.                                   Long  y2,
  660.                                   Long  miny,
  661.                                   Long  maxy )
  662.   {
  663.     Long  Dx, Dy;
  664.     Int   e1, e2, f1, f2, size;
  665.     Long  Ix, Rx, Ax;
  666.  
  667.     PStorage  top;
  668.  
  669.     Dx = x2-x1; Dy = y2-y1;
  670.  
  671.     if ( Dy <= 0 || y2 < miny || y1 > maxy ) return SUCCESS;
  672.  
  673.     if ( y1 < miny )
  674.     {
  675.       x1 += FMulDiv( Dx, miny-y1, Dy );
  676.       e1  = TRUNC( miny );
  677.       f1  = 0;
  678.     }
  679.     else
  680.     {
  681.       e1 = TRUNC( y1 );
  682.       f1 = FRAC( y1 );
  683.     }
  684.  
  685.     if ( y2 > maxy )
  686.     {
  687.       /* x2 += FMulDiv( Dx, maxy-y2, Dy );  UNNECESSARY */
  688.       e2  = TRUNC( maxy );
  689.       f2  = 0;
  690.     }
  691.     else
  692.     {
  693.       e2 = TRUNC( y2 );
  694.       f2 = FRAC( y2 );
  695.     }
  696.  
  697.     if ( f1 > 0 )
  698.       if ( e1 == e2 ) return SUCCESS;
  699.       else
  700.       {
  701.         x1 += FMulDiv( Dx, ras.precision - f1, Dy );
  702.         e1 += 1;
  703.       }
  704.     else
  705.       if ( ras.joint )
  706.       {
  707.         ras.top--;
  708.         ras.joint = FALSE;
  709.       }
  710.  
  711.     ras.joint = ( f2 == 0 );
  712.  
  713.     if ( ras.fresh )
  714.     {
  715.       ras.cProfile->start = e1;
  716.       ras.fresh           = FALSE;
  717.     }
  718.  
  719.     size = e2 - e1 + 1;
  720.     if ( ras.top + size >= ras.maxBuff )
  721.     {
  722.       ras.error = Raster_Err_Overflow;
  723.       return FAILURE;
  724.     }
  725.  
  726.     if ( Dx > 0 )
  727.     {
  728.       Ix = (ras.precision*Dx) / Dy;
  729.       Rx = (ras.precision*Dx) % Dy;
  730.       Dx = 1;
  731.     }
  732.     else
  733.     {
  734.       Ix = -( (ras.precision*-Dx) / Dy );
  735.       Rx =    (ras.precision*-Dx) % Dy;
  736.       Dx = -1;
  737.     }
  738.  
  739.     Ax  = -Dy;
  740.     top = ras.top;
  741.  
  742.     while ( size > 0 ) 
  743.     {
  744.       *top++ = x1;
  745.  
  746.       DEBUG_PSET;
  747.  
  748.       x1 += Ix;
  749.       Ax += Rx;
  750.       if ( Ax >= 0 )
  751.       {
  752.         Ax -= Dy;
  753.         x1 += Dx;
  754.       }
  755.       size--;
  756.     }
  757.  
  758.     ras.top = top;
  759.     return SUCCESS;
  760.   }
  761.  
  762.  
  763.   static Bool  Line_Down( RAS_ARGS  Long  x1, 
  764.                                     Long  y1, 
  765.                                     Long  x2, 
  766.                                     Long  y2,
  767.                                     Long  miny,
  768.                                     Long  maxy )
  769.   {
  770.     Bool result, fresh;
  771.  
  772.     fresh  = ras.fresh;
  773.  
  774.     result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
  775.  
  776.     if ( fresh && !ras.fresh ) 
  777.       ras.cProfile->start = -ras.cProfile->start;
  778.  
  779.     return result;
  780.   }
  781.  
  782. /****************************************************************************/
  783. /*                                                                          */
  784. /* Function:    Bezier_Up                                                   */
  785. /*                                                                          */
  786. /* Description: Compute the x-coordinates of an ascending bezier arc        */
  787. /*              and store them in the render pool.                          */
  788. /*                                                                          */
  789. /* Input:       None. The arc is taken from the top of the Bezier stack.    */
  790. /*                                                                          */
  791. /* Returns:     SUCCESS on success.                                         */
  792. /*              FAILURE on Render Pool overflow.                            */
  793. /*                                                                          */
  794. /****************************************************************************/
  795.  
  796.   static Bool  Bezier_Up( RAS_ARGS Long miny, Long maxy )
  797.   {
  798.     Long  y1, y2, e, e2, e0;
  799.     Int   f1;
  800.  
  801.     TPoint*  arc;
  802.     TPoint*  start_arc;
  803.  
  804.     PStorage top;
  805.  
  806.     arc = ras.arc;
  807.     y1  = arc[2].y;
  808.     y2  = arc[0].y;
  809.     top = ras.top; 
  810.  
  811.     if ( y2 < miny || y1 > maxy )
  812.       goto Fin;
  813.     
  814.     e2 = FLOOR( y2 );
  815.  
  816.     if ( e2 > maxy ) e2 = maxy;
  817.  
  818.     e0 = miny;
  819.  
  820.     if ( y1 < miny )
  821.       e = miny;
  822.     else
  823.     {
  824.       e  = CEILING( y1 );
  825.       f1 = FRAC( y1 );
  826.       e0 = e;
  827.  
  828.       if ( f1 == 0 )
  829.       {
  830.         if ( ras.joint )
  831.         {
  832.           top--;
  833.           ras.joint = FALSE;
  834.         }
  835.  
  836.         *top++ = arc[2].x;
  837.  
  838.         DEBUG_PSET;
  839.  
  840.         e += ras.precision;
  841.       }
  842.     }
  843.  
  844.     if ( ras.fresh )
  845.     {
  846.       ras.cProfile->start = TRUNC( e0 );
  847.       ras.fresh = FALSE;
  848.     }
  849.  
  850.     if ( e2 < e )
  851.       goto Fin;
  852.  
  853.     if ( ( top+TRUNC( e2-e )+1 ) >= ras.maxBuff )
  854.     {
  855.       ras.top   = top;
  856.       ras.error = Raster_Err_Overflow;
  857.       return FAILURE;
  858.     }
  859.  
  860.     start_arc = arc;
  861.  
  862.     while ( arc >= start_arc && e <= e2 )
  863.     {
  864.       ras.joint = FALSE;
  865.  
  866.       y2 = arc[0].y;
  867.  
  868.       if ( y2 > e )
  869.       {
  870.         y1 = arc[2].y;
  871.         if (  y2-y1 >= ras.precision_step )
  872.         {
  873.           Split_Bezier( arc );
  874.           arc += 2;
  875.         }
  876.         else
  877.         {
  878.           *top++ = arc[2].x + 
  879.                    FMulDiv( arc[0].x-arc[2].x, 
  880.                             e - y1, 
  881.                             y2 - y1 );
  882.           DEBUG_PSET;
  883.             
  884.           arc -= 2;
  885.           e   += ras.precision;
  886.         }
  887.       }
  888.       else
  889.       {
  890.         if ( y2 == e )
  891.         {
  892.           ras.joint  = TRUE;
  893.           *top++     = arc[0].x;
  894.         
  895.           DEBUG_PSET;
  896.         
  897.           /* Note on table overflow:                         */
  898.           /*                                                 */
  899.           /* We already know that ras.top < MaxBuff here,    */
  900.           /* so there is room for at least 1 coordinate      */
  901.           /* and we don't need to test overflow there!       */
  902.           /*                                                 */
  903.           
  904.           e += ras.precision;
  905.         }
  906.         arc -= 2;
  907.       }
  908.     }
  909.  
  910.   Fin:
  911.     ras.top  = top;
  912.     ras.arc -= 2;
  913.     return SUCCESS;
  914.   }
  915.  
  916.  
  917. /****************************************************************************/
  918. /*                                                                          */
  919. /* Function:    Bezier_Down                                                 */
  920. /*                                                                          */
  921. /* Description: Compute the x-coordinates of a descending bezier arc        */
  922. /*              and store them in the render pool.                          */
  923. /*                                                                          */
  924. /* Input:       None. Arc is taken from the top of the Bezier stack.        */
  925. /*                                                                          */
  926. /* Returns:     SUCCESS on success.                                         */
  927. /*              FAILURE on Render Pool overflow.                            */
  928. /*                                                                          */
  929. /****************************************************************************/
  930.  
  931.   static Bool  Bezier_Down( RAS_ARGS Long miny, Long maxy )
  932.   {
  933.     TPoint*  arc = ras.arc;
  934.     Bool     result, fresh;
  935.  
  936.     arc[0].y = -arc[0].y;
  937.     arc[1].y = -arc[1].y; 
  938.     arc[2].y = -arc[2].y;
  939.  
  940.     fresh = ras.fresh;
  941.  
  942.     result = Bezier_Up( RAS_VARS -maxy, -miny );
  943.  
  944.     if ( fresh && !ras.fresh )
  945.       ras.cProfile->start = -ras.cProfile->start;
  946.  
  947.     arc[0].y = -arc[0].y;
  948.     return result;
  949.   }
  950.  
  951.  
  952. /****************************************************************************/
  953. /*                                                                          */
  954. /* Function:    Line_To                                                     */
  955. /*                                                                          */
  956. /* Description: Inject a new line segment and adjust Profiles list.         */
  957. /*                                                                          */
  958. /* Input:       x, y : segment endpoint (start point in LastX,LastY)        */
  959. /*                                                                          */
  960. /* Returns:     SUCCESS on success.                                         */
  961. /*              FAILURE on Render Pool overflow or Incorrect Profile.       */
  962. /*                                                                          */
  963. /****************************************************************************/
  964.   
  965.   static Bool  Line_To( RAS_ARGS  Long  x, Long  y )
  966.   {
  967.     /* First, detect a change of direction */
  968.  
  969.     switch ( ras.state )
  970.     {
  971.     case Unknown:
  972.       if ( y > ras.lastY )
  973.       {
  974.         if ( New_Profile( RAS_VARS  Ascending ) ) return FAILURE;
  975.       }
  976.       else
  977.       {
  978.         if ( y < ras.lastY )
  979.           if ( New_Profile( RAS_VARS  Descending ) ) return FAILURE;
  980.       }
  981.       break;
  982.  
  983.     case Ascending:
  984.       if ( y < ras.lastY )
  985.       {
  986.         if ( End_Profile( RAS_VAR ) ||
  987.              New_Profile( RAS_VARS  Descending ) ) return FAILURE;
  988.       }
  989.       break;
  990.  
  991.     case Descending:
  992.       if ( y > ras.lastY )
  993.       {
  994.         if ( End_Profile( RAS_VAR ) ||
  995.              New_Profile( RAS_VARS  Ascending ) ) return FAILURE;
  996.       }
  997.       break;
  998.  
  999.     default:
  1000.       ;
  1001.     }
  1002.  
  1003.     /* Then compute the lines */
  1004.  
  1005.     switch ( ras.state )
  1006.     {
  1007.     case Ascending:
  1008.       if ( Line_Up ( RAS_VARS  ras.lastX, ras.lastY, x, y, ras.minY, ras.maxY ) ) return FAILURE;
  1009.         break;
  1010.  
  1011.     case Descending:
  1012.       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, x, y, ras.minY, ras.maxY ) ) return FAILURE;
  1013.         break;
  1014.  
  1015.     default:
  1016.       ;
  1017.     }
  1018.  
  1019.     ras.lastX = x;
  1020.     ras.lastY = y;
  1021.  
  1022.     return SUCCESS;
  1023.   }
  1024.  
  1025.  
  1026. /****************************************************************************/
  1027. /*                                                                          */
  1028. /* Function:    Bezier_To                                                   */
  1029. /*                                                                          */
  1030. /* Description: Inject a new bezier arc and adjust Profiles list.           */
  1031. /*                                                                          */
  1032. /* Input:       x,   y : arc endpoint (start point in LastX, LastY)         */
  1033. /*              Cx, Cy : control point                                      */
  1034. /*                                                                          */
  1035. /* Returns:     SUCCESS on success.                                         */
  1036. /*              FAILURE on Render Pool overflow or Incorrect Profile.       */
  1037. /*                                                                          */
  1038. /****************************************************************************/
  1039.  
  1040.   static Bool  Bezier_To( RAS_ARGS  Long  x, 
  1041.                                     Long  y, 
  1042.                                     Long  cx, 
  1043.                                     Long  cy )
  1044.   {
  1045.     Long     y1, y2, y3, x3;
  1046.     TStates  state_bez;
  1047.  
  1048.     Push_Bezier( RAS_VARS ras.lastX, ras.lastY, cx, cy, x, y );
  1049.  
  1050.     do
  1051.     {
  1052.       y1 = ras.arc[2].y;
  1053.       y2 = ras.arc[1].y;
  1054.       y3 = ras.arc[0].y;
  1055.       x3 = ras.arc[0].x;
  1056.  
  1057.       /* first, categorize the bezier arc */
  1058.  
  1059.       if ( y1 == y2 )
  1060.       {
  1061.         if ( y2 == y3 )
  1062.           state_bez = Flat;
  1063.         else if ( y2 > y3 )
  1064.           state_bez = Descending;
  1065.         else
  1066.           state_bez = Ascending;
  1067.       }
  1068.       else
  1069.       if ( y1 > y2 )
  1070.       {
  1071.         if ( y2 >= y3 )
  1072.           state_bez = Descending;
  1073.         else
  1074.           state_bez = Unknown;
  1075.       }
  1076.       else
  1077.         if ( y2 <= y3 )
  1078.           state_bez = Ascending;
  1079.         else
  1080.           state_bez = Unknown;
  1081.  
  1082.       /* split non monotonous arcs, ignore flat ones, or */
  1083.       /* computes the up and down ones                   */
  1084.  
  1085.       switch ( state_bez )
  1086.       {
  1087.       case Flat:
  1088.     ras.arc -= 2;
  1089.         break;
  1090.  
  1091.       case Unknown:
  1092.         Split_Bezier( ras.arc );
  1093.     ras.arc += 2;
  1094.         break;
  1095.  
  1096.       default:
  1097.         /* detect a change of direction */
  1098.  
  1099.         if ( ras.state != state_bez )
  1100.         {
  1101.           if ( ras.state != Unknown )
  1102.             if ( End_Profile( RAS_VAR ) ) return FAILURE;
  1103.  
  1104.           if ( New_Profile( RAS_VARS state_bez ) ) return FAILURE;
  1105.         }
  1106.  
  1107.         /* compute */
  1108.  
  1109.         switch ( ras.state )
  1110.         {
  1111.         case Ascending:
  1112.           if ( Bezier_Up  ( RAS_VARS ras.minY, ras.maxY ) ) return FAILURE;
  1113.           break;
  1114.  
  1115.         case Descending:
  1116.           if ( Bezier_Down( RAS_VARS ras.minY, ras.maxY ) ) return FAILURE;
  1117.           break;
  1118.  
  1119.         default:
  1120.           ;
  1121.         }
  1122.       }
  1123.     } while ( ras.arc >= ras.arcs );
  1124.  
  1125.     ras.lastX = x3;
  1126.     ras.lastY = y3;
  1127.  
  1128.     return SUCCESS;
  1129.   }
  1130.  
  1131.  
  1132. /****************************************************************************/
  1133. /*                                                                          */
  1134. /* Function:    Curve_To                                                    */
  1135. /*                                                                          */
  1136. /* Description: Injects several following Bezier arcs.                      */
  1137. /*                                                                          */
  1138. /* Input:       x, y : arc endpoint (start point in LastX, LastY)           */
  1139. /*                                                                          */
  1140. /*              firstCtrl, lastCtrlint : first and last control point       */
  1141. /*                                       index.                             */
  1142. /* Returns:     SUCCESS on success.                                         */
  1143. /*              FAILURE on Render Pool overflow or Incorrect Profile.       */
  1144. /*                                                                          */
  1145. /****************************************************************************/
  1146.  
  1147.   static Bool  Curve_To( RAS_ARGS  Long  x, Long  y, Int  firstCtrl, Int  lastCtrl )
  1148.   {
  1149.     Long  xz, yz, cx, cy;
  1150.  
  1151.     xz = SCALED( ras.x_coord[firstCtrl] );
  1152.     yz = SCALED( ras.y_coord[firstCtrl] );
  1153.  
  1154.     firstCtrl++;
  1155.  
  1156.     while ( firstCtrl <= lastCtrl )
  1157.     {
  1158.       cx = ( xz + SCALED( ras.x_coord[firstCtrl] ) ) / 2;
  1159.       cy = ( yz + SCALED( ras.y_coord[firstCtrl] ) ) / 2;
  1160.  
  1161.       if ( Bezier_To( RAS_VARS  cx, cy, xz, yz ) ) return FAILURE;
  1162.  
  1163.       xz = SCALED( ras.x_coord[firstCtrl] );
  1164.       yz = SCALED( ras.y_coord[firstCtrl] );
  1165.  
  1166.       firstCtrl++;
  1167.     }
  1168.  
  1169.     return Bezier_To( RAS_VARS  x, y, xz, yz );
  1170.   }
  1171.  
  1172.  
  1173. /****************************************************************************/
  1174. /*                                                                          */
  1175. /* Function:    Convert_Glyph                                               */
  1176. /*                                                                          */
  1177. /* Description: Convert a glyph into a series of segments and arcs          */
  1178. /*              and make a Profiles list with them.                         */
  1179. /*                                                                          */
  1180. /* Input:       _xCoord, _yCoord : coordinates tables.                      */
  1181. /*                                                                          */
  1182. /*              Uses the 'Flag' table too.                                  */
  1183. /*                                                                          */
  1184. /* Returns:     SUCCESS on success                                          */
  1185. /*              FAILURE if any error was encountered during rendering.      */
  1186. /*                                                                          */
  1187. /****************************************************************************/
  1188.  
  1189.  static Bool  Convert_Glyph( RAS_ARGS  PStorage  _xCoord, PStorage  _yCoord )
  1190.  {
  1191.    Int       i, j, first, last, start;
  1192.  
  1193.    PProfile  lastProfile;
  1194.  
  1195.    j            = 0;
  1196.    ras.fProfile = NULL;
  1197.    ras.joint    = FALSE;
  1198.    ras.fresh    = FALSE;
  1199.    last         = 0;
  1200.  
  1201.    ras.x_coord = _xCoord;
  1202.    ras.y_coord = _yCoord;
  1203.  
  1204.    ras.cProfile         = (PProfile)ras.top;
  1205.    ras.cProfile->offset = ras.top;
  1206.    ras.num_Profs        = 0;
  1207.  
  1208.    for ( i = 0; i < ras.nContours; i++ )
  1209.    {
  1210.      ras.state    = Unknown;
  1211.      first        = j;
  1212.      ras.lastX    = SCALED( ras.x_coord[j] );
  1213.      ras.lastY    = SCALED( ras.y_coord[j] );
  1214.      start        = 0;
  1215.      ras.gProfile = NULL;
  1216.  
  1217.      j++;
  1218.  
  1219.      while ( j <= ras.outs[i] )
  1220.      {
  1221.        if ( (ras.flags[j] & 1) == 0 )   /* OFF Curve */
  1222.          if ( start == 0 )
  1223.          {
  1224.            start = j;
  1225.            last  = j;
  1226.          }
  1227.          else
  1228.            last++;
  1229.        else                         /* ON Curve */
  1230.          if ( start != 0 )
  1231.          {
  1232.            if ( Curve_To( RAS_VARS  SCALED( ras.x_coord[j] ), 
  1233.                                     SCALED( ras.y_coord[j] ),
  1234.                                     start,
  1235.                                     last ) )
  1236.              return FAILURE;
  1237.            start = 0;
  1238.          }
  1239.          else
  1240.            if ( Line_To( RAS_VARS  SCALED( ras.x_coord[j] ),
  1241.                                    SCALED( ras.y_coord[j] ) ) )
  1242.              return FAILURE;
  1243.  
  1244.        j++;
  1245.      }
  1246.  
  1247.      if ( start != 0 )
  1248.      {
  1249.        if ( Curve_To( RAS_VARS  SCALED( ras.x_coord[first] ),
  1250.                                 SCALED( ras.y_coord[first] ),
  1251.                                 start,
  1252.                                 last ) )
  1253.          return FAILURE;
  1254.      }
  1255.      else
  1256.        if ( Line_To( RAS_VARS  SCALED( ras.x_coord[first] ),
  1257.                                SCALED( ras.y_coord[first] ) ) )
  1258.          return FAILURE;
  1259.  
  1260.      /* We must now see if the extreme arcs join or not */
  1261.  
  1262.      if ( ( FRAC( ras.lastY ) == 0 &&
  1263.             ras.lastY >= ras.minY      &&
  1264.             ras.lastY <= ras.maxY ) )
  1265.        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
  1266.          ras.top--;
  1267.        /* Note that ras.gProfile can be nil if the contour was too small */
  1268.        /* to be drawn.                                               */
  1269.  
  1270.      lastProfile = ras.cProfile;
  1271.  
  1272.      if ( End_Profile( RAS_VAR ) ) return FAILURE;
  1273.  
  1274.      if ( ras.gProfile ) lastProfile->next = ras.gProfile;
  1275.    }
  1276.  
  1277.    Finalize_Profile_Table( RAS_VAR );
  1278.  
  1279.    return SUCCESS;
  1280.  }
  1281.  
  1282.  
  1283. /************************************************/
  1284. /*                                              */
  1285. /*  Init_Linked                                 */
  1286. /*                                              */
  1287. /*    Init an empty linked list.                */
  1288. /*                                              */
  1289. /************************************************/
  1290.  
  1291.   static void  Init_Linked( TProfileList*  l )
  1292.   {
  1293.     *l = NULL;
  1294.   }
  1295.  
  1296.  
  1297. /************************************************/
  1298. /*                                              */
  1299. /*  InsNew :                                    */
  1300. /*                                              */
  1301. /*    Inserts a new Profile in a linked list.   */
  1302. /*                                              */
  1303. /************************************************/
  1304.  
  1305.   static void  InsNew( PProfileList  list,
  1306.                        PProfile      profile )
  1307.   {
  1308.     PProfile  *old, current;
  1309.     Long       x;
  1310.  
  1311.     old     = list;
  1312.     current = *old;
  1313.     x       = profile->X;
  1314.  
  1315.     while (current)
  1316.     {
  1317.       if ( x < current->X )
  1318.     goto Place;
  1319.  
  1320.       old     = ¤t->link;
  1321.       current = *old;
  1322.     }
  1323.   Place:
  1324.     profile->link = current;
  1325.     *old          = profile;
  1326.   }
  1327.  
  1328.  
  1329. /************************************************/
  1330. /*                                              */
  1331. /*  DelOld :                                    */
  1332. /*                                              */
  1333. /*    Removes an old Profile from a linked list */
  1334. /*                                              */
  1335. /************************************************/
  1336.  
  1337.   static void  DelOld( PProfileList  list,
  1338.                        PProfile      profile )
  1339.   {
  1340.     PProfile  *old, current;
  1341.  
  1342.     old     = list;
  1343.     current = *old;
  1344.  
  1345.     while ( current )
  1346.     {
  1347.       if ( current == profile )
  1348.       {
  1349.         *old = current->link;
  1350.         return;
  1351.       }
  1352.  
  1353.       old     = ¤t->link;
  1354.       current = *old;
  1355.     }
  1356.  
  1357.     /* we should never get there, unless the Profile was not part of */
  1358.     /* the list.                                                     */
  1359.   }
  1360.  
  1361.  
  1362. /************************************************/
  1363. /*                                              */
  1364. /*  Sort :                                      */
  1365. /*                                              */
  1366. /*    Sorts a trace list. In 95%, the list      */
  1367. /*    is already sorted. We need an algorithm   */
  1368. /*    which is fast in cases. Bubble sort is    */
  1369. /*    enough and simple                         */
  1370. /*                                              */
  1371. /************************************************/
  1372.  
  1373.   static void  Sort( RAS_ARGS  PProfileList  list )
  1374.   {
  1375.     PProfile  *old, current, next;
  1376.  
  1377.     /* First, set the new X coordinate of each profile */
  1378.  
  1379.     old     = list;
  1380.     current = *old;
  1381.  
  1382.     while ( current )
  1383.     {
  1384.       current->X       = *current->offset;
  1385.       current->offset += current->flow;
  1386.       current->height--;
  1387.  
  1388.       old     = ¤t->link;
  1389.       current = *old;
  1390.     }
  1391.  
  1392.     /* Then sort them */
  1393.  
  1394.     old     = list;
  1395.     current = *old;
  1396.  
  1397.     if (!current)
  1398.       return;
  1399.  
  1400.     next = current->link;
  1401.  
  1402.     while ( next )
  1403.     {
  1404.       if ( current->X <= next->X )
  1405.       {
  1406.     old     = ¤t->link;
  1407.     current = *old;
  1408.  
  1409.     if (!current)
  1410.       return;
  1411.       }
  1412.       else
  1413.       {
  1414.     *old          = next;
  1415.     current->link = next->link;
  1416.     next->link    = current;
  1417.  
  1418.     old     = list;
  1419.     current = *old;
  1420.       }
  1421.  
  1422.       next = current->link;
  1423.     }
  1424.   }
  1425.  
  1426.  
  1427. /***********************************************************************/
  1428. /*                                                                     */
  1429. /*  Vertical Sweep Procedure Set :                                     */
  1430. /*                                                                     */
  1431. /*  These three routines are used during the vertical black/white      */
  1432. /*  sweep phase by the generic Draw_Sweep function.                    */
  1433. /*                                                                     */
  1434. /***********************************************************************/
  1435.  
  1436.   static void  Vertical_Sweep_Init( RAS_ARGS  int*  min, int*  max )
  1437.   {
  1438.     switch (ras.target.flow)
  1439.       {
  1440.       case TT_Flow_Up:
  1441.         ras.traceOfs  = *min * ras.target.cols;
  1442.         ras.traceIncr = ras.target.cols;
  1443.         break;
  1444.  
  1445.       default:
  1446.         ras.traceOfs  = ( ras.target.rows - 1 - *min ) * ras.target.cols;
  1447.         ras.traceIncr = -ras.target.cols;
  1448.       }
  1449.  
  1450.     ras.gray_min_x = 0;
  1451.     ras.gray_max_x = 0;
  1452.   }
  1453.  
  1454.  
  1455.   static void  Vertical_Sweep_Span( RAS_ARGS  int         y,
  1456.                                               TT_F26Dot6  x1,
  1457.                                               TT_F26Dot6  x2,
  1458.                                               PProfile    left,
  1459.                                               PProfile    right )
  1460.   {
  1461.     Long  e1, e2;
  1462.     Int   c1, c2;
  1463.     Int   f1, f2;
  1464.     Byte* target;
  1465.  
  1466.     /* Drop-out control */
  1467.  
  1468.     e1 = TRUNC( CEILING( x1 ) );
  1469.     e2 = TRUNC( FLOOR  ( x2 ) );
  1470.  
  1471.     if ( e2 >= 0 && e1 < ras.bWidth )
  1472.     {
  1473.       if ( e1 < 0 )           e1 = 0;
  1474.       if ( e2 >= ras.bWidth ) e2 = ras.bWidth-1;
  1475.  
  1476.       c1 = e1 >> 3;
  1477.       c2 = e2 >> 3;
  1478.  
  1479.       f1 = e1 & 7;
  1480.       f2 = e2 & 7;
  1481.  
  1482.       if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
  1483.       if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
  1484.  
  1485.       target = ras.bTarget + ras.traceOfs + c1;
  1486.  
  1487.       if ( c1 != c2 )
  1488.       {
  1489.         *target |= LMask[f1];
  1490.         
  1491.         if ( c2 > c1+1 )
  1492.           MEM_Set( target + 1, 0xFF, c2-c1-1 );
  1493.         
  1494.         target[c2-c1] |= RMask[f2];
  1495.       }
  1496.       else
  1497.         *target |= ( LMask[f1] & RMask[f2] );
  1498.     }
  1499.   }
  1500.  
  1501.  
  1502.   static void  Vertical_Sweep_Drop( RAS_ARGS  int         y,
  1503.                                               TT_F26Dot6  x1,
  1504.                                               TT_F26Dot6  x2,
  1505.                                               PProfile    left,
  1506.                                               PProfile    right )
  1507.   {
  1508.     Long  e1, e2;
  1509.     Int   c1, f1;
  1510.  
  1511.     /* Drop-out control */
  1512.  
  1513.     e1 = CEILING( x1 );
  1514.     e2 = FLOOR  ( x2 );
  1515.  
  1516.     if ( e1 > e2 )
  1517.     {
  1518.       if ( e1 == e2 + ras.precision )
  1519.       {
  1520.         switch ( ras.dropOutControl )
  1521.         {
  1522.         case 1:
  1523.           e1 = e2;
  1524.           break;
  1525.  
  1526.         case 4:
  1527.           e1 = CEILING( (x1+x2+1) / 2 );
  1528.           e2 = e1;
  1529.           break;
  1530.  
  1531.         case 2:
  1532.         case 5:
  1533.           /* Drop-out Control Rule #4 */
  1534.   
  1535.           /* The spec is not very clear regarding rule #4. It       */
  1536.           /* presents a method that is way too costly to implement  */
  1537.           /* while the general idea seems to get rid of 'stubs'.    */
  1538.           /*                                                        */
  1539.           /* Here, we only get rid of stubs recognized when :       */
  1540.           /*                                                        */
  1541.           /*  upper stub :                                          */
  1542.           /*                                                        */
  1543.           /*   - P_Left and P_Right are in the same contour         */
  1544.           /*   - P_Right is the successor of P_Left in that contour */
  1545.           /*   - y is the top of P_Left and P_Right                 */
  1546.           /*                                                        */
  1547.           /*  lower stub :                                          */
  1548.           /*                                                        */
  1549.           /*   - P_Left and P_Right are in the same contour         */
  1550.           /*   - P_Left is the successor of P_Right in that contour */
  1551.           /*   - y is the bottom of P_Left                          */
  1552.           /*                                                        */
  1553.  
  1554.           /* upper stub test */
  1555.  
  1556.           if ( left->next == right && left->height <= 0 ) return;
  1557.  
  1558.           /* lower stub test */
  1559.  
  1560.           if ( right->next == left && left->start == y ) return;
  1561.  
  1562.           /* check that the rightmost pixel isn't set */
  1563.  
  1564.           e1 = TRUNC( e1 );
  1565.  
  1566.           c1 = e1 >> 3;
  1567.           f1 = e1 &  7;
  1568.  
  1569.           if ( e1 >= 0 && e1 < ras.bWidth &&
  1570.                ras.bTarget[ras.traceOfs + c1] & (0x80 >> f1) ) return;
  1571.  
  1572.                   if ( ras.dropOutControl == 2 )
  1573.                     e1 = e2;
  1574.                   else
  1575.                     e1 = CEILING( (x1+x2+1)/2 );
  1576.                     
  1577.           break;
  1578.  
  1579.         default:
  1580.           return;  /* unsupported mode */
  1581.         }
  1582.       }
  1583.       else
  1584.         return;
  1585.     }
  1586.     else
  1587.       e2 = e1;
  1588.  
  1589.     e1 = TRUNC( e1 );
  1590.  
  1591.     if ( e1 >= 0 && e1 < ras.bWidth )
  1592.     {
  1593.       c1 = e1 >> 3;
  1594.       f1 = e1 & 7;
  1595.  
  1596.       if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
  1597.       if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
  1598.  
  1599.       ras.bTarget[ras.traceOfs+c1] |= (0x80 >> f1);
  1600.     }
  1601.   }
  1602.  
  1603.  
  1604.   static void Vertical_Sweep_Step( RAS_ARG )
  1605.   {
  1606.     ras.traceOfs += ras.traceIncr;
  1607.   }
  1608.  
  1609.  
  1610. /***********************************************************************/
  1611. /*                                                                     */
  1612. /*  Horizontal Sweep Procedure Set :                                   */
  1613. /*                                                                     */
  1614. /*  These three routines are used during the horizontal black/white    */
  1615. /*  sweep phase by the generic Draw_Sweep function.                    */
  1616. /*                                                                     */
  1617. /***********************************************************************/
  1618.  
  1619.   static void  Horizontal_Sweep_Init( RAS_ARGS  int*  min, int*  max )
  1620.   {
  1621.     /* nothing, really */
  1622.   }
  1623.  
  1624.  
  1625.   static void  Horizontal_Sweep_Span( RAS_ARGS  int         y,
  1626.                                                 TT_F26Dot6  x1,
  1627.                                                 TT_F26Dot6  x2,
  1628.                                                 PProfile    left,
  1629.                                                 PProfile    right )
  1630.   {
  1631.     Long  e1, e2;
  1632.     Int   c1;
  1633.     Int   f1;
  1634.  
  1635.     /* During the horizontal sweep, we only take care of drop-outs */
  1636.  
  1637.     e1 = CEILING( x1 );
  1638.     e2 = FLOOR  ( x2 );
  1639.  
  1640.     c1 = y >> 3;
  1641.     f1 = y  & 7;
  1642.  
  1643.     e1 = TRUNC( e1 );
  1644.  
  1645.     if ( e1 >= 0 && e1 < ras.target.rows )
  1646.       if ( ras.target.flow == TT_Flow_Down )
  1647.         ras.bTarget[c1 + (ras.target.rows - 1 - e1) * ras.target.cols] |= (0x80 >> f1);
  1648.       else
  1649.         ras.bTarget[c1 + e1 * ras.target.cols] |= (0x80 >> f1);
  1650.  
  1651.     e2 = TRUNC( e2 );
  1652.  
  1653.     if ( e2 >= 0 && e2 < ras.target.rows )
  1654.       if ( ras.target.flow == TT_Flow_Down )
  1655.         ras.bTarget[c1 + (ras.target.rows - 1 - e2) * ras.target.cols] |= (0x80 >> f1);
  1656.       else
  1657.         ras.bTarget[c1 + e2 * ras.target.cols] |= (0x80 >> f1);
  1658.   }
  1659.  
  1660.  
  1661.   static void  Horizontal_Sweep_Drop( RAS_ARGS  int         y,
  1662.                                                 TT_F26Dot6  x1,
  1663.                                                 TT_F26Dot6  x2,
  1664.                                                 PProfile    left,
  1665.                                                 PProfile    right )
  1666.   {
  1667.     Long  e1, e2;
  1668.     Int   c1;
  1669.     Int   f1;
  1670.  
  1671.     Byte* target;
  1672.  
  1673.     /* During the horizontal sweep, we only take care of drop-outs */
  1674.  
  1675.     e1 = CEILING( x1 );
  1676.     e2 = FLOOR  ( x2 );
  1677.  
  1678.     if ( e1 > e2 )
  1679.     {
  1680.       if ( e1 == e2 + ras.precision )
  1681.       {
  1682.         switch ( ras.dropOutControl )
  1683.         {
  1684.         case 1:
  1685.           e1 = e2;
  1686.           break;
  1687.  
  1688.         case 4:
  1689.           e1 = CEILING( (x1+x2+1) / 2 );
  1690.           break;
  1691.  
  1692.         case 2:
  1693.         case 5:
  1694.  
  1695.           /* Drop-out Control Rule #4 */
  1696.   
  1697.           /* The spec is not very clear regarding rule #4. It       */
  1698.           /* presents a method that is way too costly to implement  */
  1699.           /* while the general idea seems to get rid of 'stubs'.    */
  1700.           /*                                                        */
  1701.  
  1702.           /* rightmost stub test */
  1703.  
  1704.           if ( left->next == right && left->height <= 0 ) return;
  1705.  
  1706.           /* leftmost stub test */
  1707.  
  1708.           if ( right->next == left && left->start == y ) return;
  1709.  
  1710.           /* check that the rightmost pixel isn't set */
  1711.  
  1712.           e1 = TRUNC( e1 );
  1713.  
  1714.           c1 = y >> 3;
  1715.           f1 = y &  7;
  1716.  
  1717.           if ( ras.target.flow == TT_Flow_Down )
  1718.             target = ras.bTarget + c1 + (ras.target.rows - 1 - e1) * 
  1719.                                          ras.target.cols;
  1720.           else
  1721.             target = ras.bTarget + c1 + e1 * ras.target.cols;
  1722.  
  1723.           if ( e1 >= 0 && e1 < ras.target.rows &&
  1724.                *target & (0x80 >> f1) ) return;
  1725.  
  1726.           if ( ras.dropOutControl == 2 )
  1727.             e1 = e2;
  1728.           else
  1729.             e1 = CEILING( (x1+x2+1) / 2 );
  1730.  
  1731.           break;
  1732.  
  1733.         default:
  1734.           return;  /* unsupported mode */
  1735.         }
  1736.       }
  1737.       else
  1738.         return;
  1739.     }
  1740.  
  1741.     c1 = y >> 3;
  1742.     f1 = y  & 7;
  1743.  
  1744.     e1 = TRUNC( e1 );
  1745.  
  1746.     if ( e1 >= 0 && e1 < ras.target.rows )
  1747.       if (ras.target.flow==TT_Flow_Down)
  1748.         ras.bTarget[c1 + (ras.target.rows-1-e1)*ras.target.cols] |= (0x80 >> f1);
  1749.     else
  1750.         ras.bTarget[c1 + e1*ras.target.cols] |= (0x80 >> f1);
  1751.   }
  1752.  
  1753.  
  1754.   static void Horizontal_Sweep_Step( RAS_ARG )
  1755.   {
  1756.     /* Nothing, really */
  1757.   }
  1758.  
  1759.  
  1760. /***********************************************************************/
  1761. /*                                                                     */
  1762. /*  Vertical Gray Sweep Procedure Set :                                */
  1763. /*                                                                     */
  1764. /*  These two routines are used during the vertical gray-levels        */
  1765. /*  sweep phase by the generic Draw_Sweep function.                    */
  1766. /*                                                                     */
  1767. /*                                                                     */
  1768. /*  NOTES :                                                            */
  1769. /*                                                                     */
  1770. /*  - The target pixmap's width *must* be a multiple of 4.             */
  1771. /*                                                                     */
  1772. /*  - you have to use the function Vertical_Sweep_Span for             */
  1773. /*    the gray span call.                                              */
  1774. /*                                                                     */
  1775. /***********************************************************************/
  1776.  
  1777.   static void  Gray_Sweep_Init( RAS_ARGS  int*  min, int*  max )
  1778.   {
  1779.     *min = *min & -2;
  1780.     *max = ( *max+3 ) & -2;
  1781.  
  1782.     ras.traceOfs = 0;
  1783.  
  1784.     switch (ras.target.flow)
  1785.       {
  1786.       case TT_Flow_Up:
  1787.         ras.traceG  = (*min/2) * ras.target.cols;
  1788.         ras.traceIncr = ras.target.cols;
  1789.         break;
  1790.  
  1791.       default:
  1792.         ras.traceG    = (ras.target.rows-1 - *min/2) * ras.target.cols;
  1793.         ras.traceIncr = -ras.target.cols;
  1794.       }
  1795.  
  1796.     ras.gray_min_x =  ras.target.cols;
  1797.     ras.gray_max_x = -ras.target.cols;
  1798.   }
  1799.  
  1800.  
  1801.   static void Gray_Sweep_Step( RAS_ARG )
  1802.   {
  1803.     Int    c1, c2;
  1804.     PByte  pix, bit, bit2;
  1805.     Int*   count = ras.count_table;
  1806.     char*  grays;
  1807.  
  1808.     ras.traceOfs += ras.gray_width;
  1809.  
  1810.     if ( ras.traceOfs > ras.gray_width )
  1811.     {
  1812.       pix   = ras.gTarget + ras.traceG + ras.gray_min_x*4;
  1813.       grays = ras.grays;
  1814.  
  1815.       if ( ras.gray_max_x >= 0 )
  1816.       {
  1817.         if ( ras.gray_max_x >= ras.target.width ) 
  1818.       ras.gray_max_x = ras.target.width - 1;
  1819.  
  1820.         if ( ras.gray_min_x < 0 ) 
  1821.       ras.gray_min_x = 0;
  1822.  
  1823.     bit   = ras.bTarget + ras.gray_min_x;
  1824.     bit2  = bit + ras.gray_width; 
  1825.     
  1826.     c1 = ras.gray_max_x - ras.gray_min_x;
  1827.  
  1828.         while (c1 >= 0)
  1829.         {
  1830.           c2 = count[ *bit ] + count[ *bit2 ];
  1831.  
  1832.           if (c2)
  1833.           {
  1834.         pix[0] = grays[(c2 & 0xF000) >> 12];
  1835.         pix[1] = grays[(c2 & 0x0F00) >>  8];
  1836.         pix[2] = grays[(c2 & 0x00F0) >>  4];
  1837.         pix[3] = grays[(c2 & 0x000F)      ];
  1838.  
  1839.         *bit  = 0;
  1840.         *bit2 = 0;
  1841.           }
  1842.  
  1843.       bit  ++;
  1844.       bit2 ++;
  1845.       pix  += 4;
  1846.       c1   --;
  1847.         }
  1848.       }
  1849.  
  1850.       ras.traceOfs = 0;
  1851.       ras.traceG  += ras.traceIncr;
  1852.  
  1853.       ras.gray_min_x =  ras.target.cols;
  1854.       ras.gray_max_x = -ras.target.cols;
  1855.     }
  1856.   }
  1857.  
  1858.  
  1859. /********************************************************************/
  1860. /*                                                                  */
  1861. /*  Generic Sweep Drawing routine                                   */
  1862. /*                                                                  */
  1863. /********************************************************************/
  1864.  
  1865.   static Bool  Draw_Sweep( RAS_ARG )
  1866.   {
  1867.     Int  y;
  1868.  
  1869.     PProfile  P, Q, P_Left, P_Right, Q_Left, Q_Right;
  1870.  
  1871.     Int  min_Y, max_Y, top, bottom, dropouts;
  1872.  
  1873.     Long x1, x2, xs, e1, e2;
  1874.  
  1875.     TProfileList  wait;
  1876.     TProfileList  draw_left, draw_right;
  1877.     TProfileList  drop_left, drop_right;
  1878.  
  1879.     /* Init empty linked lists */
  1880.  
  1881.     Init_Linked( &wait );
  1882.  
  1883.     Init_Linked( &draw_left  );
  1884.     Init_Linked( &draw_right );
  1885.  
  1886.     Init_Linked( &drop_left  );
  1887.     Init_Linked( &drop_right );
  1888.  
  1889.     /* first, compute min and max Y */
  1890.  
  1891.     P     = ras.fProfile;
  1892.     max_Y = TRUNC( ras.minY );
  1893.     min_Y = TRUNC( ras.maxY );
  1894.  
  1895.     while ( P )
  1896.     {
  1897.       Q = P->link;
  1898.  
  1899.       switch ( P->flow )
  1900.       {
  1901.       case TT_Flow_Up:
  1902.         bottom = P->start;
  1903.         top    = P->start + P->height - 1;
  1904.         break;
  1905.  
  1906.       case TT_Flow_Down:
  1907.         bottom = P->start - P->height + 1;
  1908.         top    = P->start;
  1909.  
  1910.         P->start   = bottom;
  1911.         P->offset += P->height - 1;
  1912.         break;
  1913.  
  1914.       default:
  1915.         ras.error = Raster_Err_Invalid;
  1916.         return FAILURE;
  1917.       }
  1918.  
  1919.       if ( min_Y > bottom ) min_Y = bottom;
  1920.       if ( max_Y < top    ) max_Y = top;
  1921.  
  1922.       P->X = 0;
  1923.       InsNew( &wait, P );
  1924.  
  1925.       P = Q;
  1926.     }
  1927.  
  1928.     /* Now inits the sweep */
  1929.  
  1930.     ras.Proc_Sweep_Init( RAS_VARS  &min_Y, &max_Y );
  1931.  
  1932.     /* Then compute the distance of each profile from min_Y */
  1933.  
  1934.     P = wait;
  1935.  
  1936.     while ( P )
  1937.     {
  1938.       P->countL = P->start - min_Y;
  1939.       P = P->link;
  1940.     }
  1941.  
  1942.     /* Let's go */
  1943.  
  1944.     for ( y = min_Y; y <= max_Y; y++ )
  1945.     {
  1946.       /* look in the wait list for new activations */
  1947.  
  1948.       P = wait;
  1949.  
  1950.       while ( P )
  1951.       {
  1952.     Q = P->link;
  1953.         if ( P->countL == 0 )
  1954.         {
  1955.           DelOld( &wait, P );
  1956.           switch ( P->flow )
  1957.           {
  1958.           case TT_Flow_Up:
  1959.             InsNew( &draw_left,  P );
  1960.             break;
  1961.           case TT_Flow_Down:
  1962.             InsNew( &draw_right, P );
  1963.             break;
  1964.           }
  1965.         }
  1966.         else
  1967.           P->countL--;
  1968.  
  1969.         P = Q;
  1970.       }
  1971.  
  1972.       /* Sort the drawing lists */
  1973.  
  1974.       Sort( RAS_VARS  &draw_left );
  1975.       Sort( RAS_VARS  &draw_right );
  1976.  
  1977.       /* Let's trace */
  1978.  
  1979.       dropouts = 0;
  1980.  
  1981.       P_Left  = draw_left;
  1982.       P_Right = draw_right;
  1983.  
  1984.       while ( P_Left )
  1985.       {
  1986.     Q_Left  = P_Left ->link;
  1987.     Q_Right = P_Right->link;
  1988.  
  1989.         x1 = P_Left ->X;
  1990.         x2 = P_Right->X;
  1991.  
  1992. #ifdef IGNORE_FILL_FLOW
  1993.         if (x1 > x2)
  1994.         {
  1995.           xs = x1;
  1996.           x1 = x2;
  1997.           x2 = xs;
  1998.         }
  1999. #endif
  2000.  
  2001.         if ( ras.dropOutControl != 0 && x2-x1 <= ras.precision )
  2002.         {
  2003.           e1 = FLOOR(x1);
  2004.           e2 = CEILING(x2);
  2005.  
  2006.           if ( e1 > e2 || e2 == e1 + ras.precision )
  2007.           {
  2008.             /* a drop out was detected */
  2009.  
  2010.             P_Left ->X = x1;
  2011.             P_Right->X = x2;
  2012.  
  2013.             dropouts++;
  2014.  
  2015.             DelOld( &draw_left,  P_Left  );
  2016.             DelOld( &draw_right, P_Right );
  2017.  
  2018.             InsNew( &drop_left,  P_Left  );
  2019.             InsNew( &drop_right, P_Right );
  2020.  
  2021.             goto Skip_To_Next;
  2022.           }
  2023.         }
  2024.  
  2025.         ras.Proc_Sweep_Span( RAS_VARS  y, x1, x2, P_Left, P_Right );
  2026.  
  2027.         /* We finalize the profile if needed */
  2028.  
  2029.         if (P_Left->height <= 0)
  2030.           DelOld( &draw_left, P_Left );
  2031.  
  2032.         if (P_Right->height <= 0)
  2033.           DelOld( &draw_right, P_Right );
  2034.  
  2035.    Skip_To_Next:
  2036.  
  2037.         P_Left  = Q_Left;
  2038.         P_Right = Q_Right;
  2039.       }
  2040.  
  2041.       P_Left  = drop_left;
  2042.       P_Right = drop_right;
  2043.  
  2044.       while (dropouts > 0)
  2045.       {
  2046.         Q_Left  = P_Left->link;
  2047.         Q_Right = P_Right->link;
  2048.  
  2049.         DelOld( &drop_left,  P_Left  );
  2050.         DelOld( &drop_right, P_Right );
  2051.  
  2052.         ras.Proc_Sweep_Drop( RAS_VARS y, 
  2053.                                       P_Left->X, 
  2054.                                       P_Right->X, 
  2055.                                       P_Left, 
  2056.                                       P_Right );
  2057.  
  2058.         if (P_Left->height > 0)
  2059.           InsNew( &draw_left, P_Left );
  2060.  
  2061.         if (P_Right->height > 0)
  2062.           InsNew( &draw_right, P_Right );
  2063.  
  2064.         P_Left  = Q_Left;
  2065.         P_Right = Q_Right;
  2066.  
  2067.         dropouts--;
  2068.       }
  2069.  
  2070.       /* Step to next line */
  2071.  
  2072.       ras.Proc_Sweep_Step( RAS_VAR );
  2073.     }
  2074.  
  2075.     return SUCCESS;
  2076.   }
  2077.  
  2078.  
  2079. /****************************************************************************/
  2080. /*                                                                          */
  2081. /* Function:    Render_Single_Pass                                          */
  2082. /*                                                                          */
  2083. /* Description: Performs one sweep with sub-banding.                        */
  2084. /*                                                                          */
  2085. /* Input:       _XCoord, _YCoord : x and y coordinates arrays               */
  2086. /*                                                                          */
  2087. /* Returns:     SUCCESS on success                                          */
  2088. /*              FAILURE if any error was encountered during render.         */
  2089. /*                                                                          */
  2090. /****************************************************************************/
  2091.  
  2092.   static TT_Error  Render_Single_Pass( RAS_ARGS  TT_F26Dot6*  _xcoord,
  2093.                                                  TT_F26Dot6*  _ycoord )
  2094.   {
  2095.     Int  i, j, k;
  2096.  
  2097.     while ( ras.band_top >= 0 )
  2098.     {
  2099.       ras.maxY = ras.band_stack[ras.band_top].y_max * ras.precision;
  2100.       ras.minY = ras.band_stack[ras.band_top].y_min * ras.precision;
  2101.  
  2102.       ras.top = ras.buff;
  2103.  
  2104.       ras.error = Raster_Err_None;
  2105.  
  2106.       if ( Convert_Glyph( RAS_VARS  _xcoord, _ycoord ) )
  2107.       {
  2108.         if ( ras.error != Raster_Err_Overflow ) return FAILURE;
  2109.  
  2110.         ras.error = Raster_Err_None;
  2111.  
  2112.         /* sub-banding */
  2113.  
  2114. #ifdef DEBUG_RASTER
  2115.         ClearBand( RAS_VARS  TRUNC( ras.minY ), TRUNC( ras.maxY ) );
  2116. #endif
  2117.  
  2118.         i = ras.band_stack[ras.band_top].y_min;
  2119.         j = ras.band_stack[ras.band_top].y_max;
  2120.  
  2121.         k = ( i + j )/2;
  2122.  
  2123.         if ( ras.band_top >= 7 || k < i )
  2124.         {
  2125.           ras.band_top     = 0;
  2126.           ras.error = Raster_Err_Invalid;
  2127.           return ras.error;
  2128.         }
  2129.  
  2130.         ras.band_stack[ras.band_top+1].y_min = k;
  2131.         ras.band_stack[ras.band_top+1].y_max = j;
  2132.  
  2133.         ras.band_stack[ras.band_top].y_max = k - 1;
  2134.  
  2135.         ras.band_top++;
  2136.       }
  2137.       else
  2138.       {
  2139.         if ( ras.fProfile )
  2140.           if ( Draw_Sweep( RAS_VAR ) ) return ras.error;
  2141.         ras.band_top--;
  2142.       }
  2143.     }
  2144.  
  2145.     return TT_Err_Ok;
  2146.   }
  2147.  
  2148.  
  2149. /****************************************************************************/
  2150. /*                                                                          */
  2151. /* Function:    Render_Glyph                                                */
  2152. /*                                                                          */
  2153. /* Description: Renders a glyph in a bitmap.      Sub-banding if needed.    */
  2154. /*                                                                          */
  2155. /* Input:       AGlyph   Glyph record                                       */
  2156. /*                                                                          */
  2157. /* Returns:     SUCCESS on success.                                         */
  2158. /*              FAILURE if any error was encountered during rendering.      */
  2159. /*                                                                          */
  2160. /****************************************************************************/
  2161.  
  2162.   TT_Error  Render_Glyph( RAS_ARGS  TT_Glyph_Outline*  glyph,
  2163.                                     TT_Raster_Map*     target_map )
  2164.   {
  2165.     TT_Error  error;
  2166.  
  2167.     if ( !ras.buff )
  2168.     {
  2169.       ras.error = Raster_Err_Not_Ini;
  2170.       return ras.error;
  2171.     }
  2172.  
  2173.     if ( target_map )
  2174.       ras.target = *target_map;
  2175.  
  2176.     ras.outs      = glyph->conStarts;
  2177.     ras.flags     = glyph->flag;
  2178.     ras.nPoints   = glyph->points;
  2179.     ras.nContours = glyph->contours;
  2180.  
  2181.     ras.dropOutControl = glyph->dropout_mode;
  2182.  
  2183.     /* Vertical Sweep */
  2184.  
  2185.     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
  2186.     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
  2187.     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
  2188.     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
  2189.  
  2190.     ras.band_top            = 0;
  2191.     ras.band_stack[0].y_min = 0;
  2192.     ras.band_stack[0].y_max = ras.target.rows - 1;
  2193.  
  2194.     ras.bWidth  = ras.target.width;
  2195.     ras.bTarget = (unsigned char*)ras.target.bitmap;
  2196.  
  2197.     if ( (error = Render_Single_Pass( RAS_VARS glyph->xCoord, 
  2198.                                                glyph->yCoord )) )
  2199.       return error;
  2200.  
  2201.     /* Horizontal Sweep */
  2202.  
  2203.     if ( ras.second_pass && ras.dropOutControl != 0 )
  2204.     {
  2205.       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
  2206.       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
  2207.       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
  2208.       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
  2209.  
  2210.       ras.band_top            = 0;
  2211.       ras.band_stack[0].y_min = 0;
  2212.       ras.band_stack[0].y_max = ras.target.width - 1;
  2213.  
  2214.       if ( (error = Render_Single_Pass( RAS_VARS glyph->yCoord, 
  2215.                                                  glyph->xCoord )) )
  2216.         return error;
  2217.     }
  2218.  
  2219.     return TT_Err_Ok;
  2220.   }
  2221.  
  2222.  
  2223. /****************************************************************************/
  2224. /*                                                                          */
  2225. /* Function:    Render_Gray_Glyph                                           */
  2226. /*                                                                          */
  2227. /* Description: Renders a glyph with grayscaling. Sub-banding if needed.    */
  2228. /*                                                                          */
  2229. /* Input:       AGlyph   Glyph record                                       */
  2230. /*                                                                          */
  2231. /* Returns:     SUCCESS on success                                          */
  2232. /*              FAILURE if any error was encountered during rendering.      */
  2233. /*                                                                          */
  2234. /****************************************************************************/
  2235.  
  2236.   TT_Error  Render_Gray_Glyph( RAS_ARGS  TT_Glyph_Outline*  glyph,
  2237.                                          TT_Raster_Map*     target_map,
  2238.                                          char*              palette )
  2239.   {
  2240.     Int i;
  2241.  
  2242.     if ( !ras.buff )
  2243.     {
  2244.       ras.error = Raster_Err_Not_Ini;
  2245.       return ras.error;
  2246.     }
  2247.  
  2248.     if ( palette )
  2249.     {
  2250.       for ( i = 0; i < 5; i++ ) ras.grays[i] = palette[i];
  2251.     }
  2252.  
  2253.     if ( target_map )
  2254.       ras.target = *target_map;
  2255.  
  2256.     ras.outs      = glyph->conStarts;
  2257.     ras.flags     = glyph->flag;
  2258.     ras.nPoints   = glyph->points;
  2259.     ras.nContours = glyph->contours;
  2260.  
  2261.     ras.dropOutControl = glyph->dropout_mode;
  2262.  
  2263.     /* Vertical Sweep */
  2264.  
  2265.     ras.band_top            = 0;
  2266.     ras.band_stack[0].y_min = 0;
  2267.     ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
  2268.  
  2269.     ras.bWidth  = ras.gray_width;
  2270.     if ( ras.bWidth > ras.target.cols/4 ) ras.bWidth = ras.target.cols/4;
  2271.  
  2272.     ras.bWidth  = ras.bWidth * 8;
  2273.     ras.bTarget = (unsigned char*)ras.gray_lines;
  2274.     ras.gTarget = (unsigned char*)ras.target.bitmap;
  2275.  
  2276.     ras.Proc_Sweep_Init = Gray_Sweep_Init;
  2277.     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
  2278.     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
  2279.     ras.Proc_Sweep_Step = Gray_Sweep_Step;
  2280.  
  2281.     return Render_Single_Pass( RAS_VARS  glyph->xCoord, glyph->yCoord );
  2282.   }
  2283.  
  2284.  
  2285. /************************************************/
  2286. /*                                              */
  2287. /* InitRasterizer                               */
  2288. /*                                              */
  2289. /*  Raster Initialization.                      */
  2290. /*  Get the bitmap description and render pool  */
  2291. /*  addresses.                                  */
  2292. /*                                              */
  2293. /************************************************/
  2294.  
  2295. #undef ras
  2296.  
  2297.   TT_Error  TTRaster_Done()
  2298.   {
  2299.     TRaster_Instance*  ras = (TRaster_Instance*)engine.raster_component;
  2300.  
  2301.     if (!ras)
  2302.       return TT_Err_Ok;
  2303.  
  2304.     FREE( ras->buff );
  2305.     FREE( ras->gray_lines );
  2306.  
  2307.     #ifndef TT_STATIC_RASTER
  2308.     FREE( engine.raster_component );
  2309.     #endif
  2310.  
  2311.     return TT_Err_Ok;
  2312.   }
  2313.  
  2314.  
  2315.  
  2316.   TT_Error  TTRaster_Init()
  2317.   {
  2318.     TT_Error  error;
  2319.  
  2320.     int  i, l, j, c;
  2321.  
  2322.     TRaster_Instance*  ras;
  2323.  
  2324.     #ifdef TT_STATIC_RASTER
  2325.       ras = engine.raster_component = &cur_ras;
  2326.     #else
  2327.       if ( ALLOC( engine.raster_component, sizeof(TRaster_Instance) ))
  2328.         return error;
  2329.  
  2330.       ras = (TRaster_Instance*)engine.raster_component;
  2331.     #endif
  2332.  
  2333.     if ( ALLOC( ras->buff,       RASTER_RENDER_POOL )  ||
  2334.          ALLOC( ras->gray_lines, RASTER_GRAY_LINES ) )
  2335.        return error;
  2336.  
  2337.     ras->maxBuff    = ras->buff + ( RASTER_RENDER_POOL / 4 ) 
  2338.                       - AlignProfileSize;
  2339.  
  2340.     ras->gray_width = RASTER_GRAY_LINES / 2;
  2341.  
  2342.     /* Initialization of Count_Table */
  2343.  
  2344.     for ( i = 0; i < 256; i++ )
  2345.     {
  2346.       l = 0;
  2347.       j = i;
  2348.       for ( c = 0; c < 4; c++ )
  2349.       {
  2350.         l <<= 4;
  2351.  
  2352.         if ( j & 0x80 ) l++;
  2353.         if ( j & 0x40 ) l++;
  2354.  
  2355.         j = ( j << 2 ) & 0xFF;
  2356.       }
  2357.  
  2358.       ras->count_table[i] = l;
  2359.     }
  2360.  
  2361.     ras->dropOutControl = 2;
  2362.     ras->error          = Raster_Err_None;
  2363.  
  2364.     #ifdef TT_STATIC_RASTER
  2365.       Set_Second_Pass( ras, FALSE );
  2366.       Set_High_Precision( ras, FALSE );
  2367.  
  2368.       /* I Can't understand why I can't write a simple line like : */
  2369.       /*                                                           */
  2370.       /*   Set_High_Precision( FALSE ) which gives me with GCC :   */
  2371.       /*                                                           */
  2372.       /*   ttraster.c:2653: too few arguments to function          */
  2373.       /*                      `Set_High_Precision'                 */
  2374.       /*                                                           */
  2375.       /*   Could someone explain this to me ??   - DavidT          */
  2376.       /*                                                           */
  2377.  
  2378.     #else
  2379.       Set_Second_Pass( ras, FALSE );
  2380.       Set_High_Precision( ras, FALSE );
  2381.     #endif
  2382.  
  2383.     return TT_Err_Ok;
  2384.   }
  2385.  
  2386.  
  2387. /* End */
  2388.