📄 ftraster.c
字号:
/* exactly on a scanline. Allows */ /* removal of doublets */ PProfile cur_prof; /* current profile */ PProfile start_prof; /* head of linked list of profiles */ PProfile first_prof; /* contour's first profile in case */ /* of impact */ TDirection state; /* rendering state */ FT_Bitmap target; /* description of target bit/pixmap */ int trace_bit; /* current offset in target bitmap */ int trace_pix; /* current offset in target pixmap */ int trace_incr; /* sweep's increment in target bitmap */ /* dispatch variables */ Raster_Render render; int scale_shift; /* == 0 for bitmaps */ /* == 1 for 5-levels pixmaps */ /* == 2 for 17-levels pixmaps */ int scale_delta; /* ras.precision_half for bitmaps */ /* 0 for pixmaps */ char dropout_mode; /* current drop_out control method */ char second_pass; /* indicates whether a horizontal pass */ /* should be performed to control drop-out */ /* accurately when calling Render_Glyph. */ /* Note that there is no horizontal pass */ /* during gray rendering. */ char flipped; /* this flag is set during the rendering to */ /* indicate the second pass. */ TBand band_stack[16]; /* band stack used for sub-banding */ int band_top; /* band stack top */ TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */ };#ifdef DEBUG_RASTER /*************************************************************************/ /* */ /* <Function> */ /* Pset */ /* */ /* <Description> */ /* Used for debugging only. Plots a point in VRAM during rendering */ /* (not afterwards). */ /* */ /* <Note> */ /* This procedure relies on the value of cProfile->start, which may */ /* not be set when Pset() is called sometimes. This will usually */ /* result in a dot plotted on the first screen scanline (far away */ /* from its original position). */ /* */ /* This `feature' reflects nothing wrong in the current */ /* implementation, and the bitmap is rendered correctly, so don't */ /* panic if you see `flying' dots in debugging mode. */ /* */ static void Pset( RAS_ARG ) { long o; long x; x = ras.cursor[-1]; switch ( ras.cur_prof->flow ) { case FT_Flow_Up: o = Vio_ScanLineWidth * ( ras.cursor - ras.cur_prof->offset + ras.cur_prof->start ) + ( x / (PRECISION * 8) ); break; case FT_Flow_Down: o = Vio_ScanLineWidth * ( ras.cur_prof->start - ras.cursor + ras.cur_prof->offset ) + ( x / (PRECISION * 8) ); break; } if ( o > 0 ) Vio[o] |= (unsigned)0x80 >> ( (x/PRECISION) & 7 ); } static void Clear_Band( RAS_ARG_ TScan y1, TScan y2 ) { MEM_Set( Vio + y1*Vio_ScanLineWidth, (y2-y1+1)*Vio_ScanLineWidth, 0 ); }#endif /* DEBUG_RASTER */ /*************************************************************************/ /* */ /* <Function> */ /* Set_High_Precision */ /* */ /* <Description> */ /* Sets precision variables according to the parameter flag. */ /* */ /* <Input> */ /* High :: Set to True for high precision (typically for ppem < 18), */ /* false otherwise. */ /* */ static void Set_High_Precision( RAS_ARG_ char High ) {#ifdef FT_RASTER_CONSTANT_PRECISION (void)High; (void)&ras;#else if ( High ) { ras.precision_bits = 10; ras.precision_step = 128; ras.precision_jitter = 24; } else { ras.precision_bits = 6; ras.precision_step = 32; ras.precision_jitter = 2; } ras.precision = 1L << ras.precision_bits; ras.precision_half = ras.precision / 2; ras.precision_shift = ras.precision_bits - INPUT_BITS; ras.precision_mask = -ras.precision;#endif } /*************************************************************************/ /* */ /* A simple technical note on how the raster works: */ /* */ /* Converting an outline into a bitmap is achieved in several steps */ /* which are: */ /* */ /* 1 - Decomposing the outline into successive `profiles'. Each */ /* profile is simply an array of scanline intersections on a given */ /* dimension. A profile's main attributes are */ /* */ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */ /* */ /* o an array of intersection coordinates for each scanline */ /* between `Ymin' and `Ymax'. */ /* */ /* o a direction, indicating wether is was built going `up' or */ /* `down', as this is very important for filling rules. */ /* */ /* 2 - Sweeping the target map's scanlines in order to compute segment */ /* `spans' which are then filled. Additionaly, this pass performs */ /* drop-out control. */ /* */ /* The outline data is parsed during step 1 only. The profiles are */ /* built from the bottom of the render pool, used as a stack. The */ /* following graphics shows the profile list under construction: */ /* */ /* ____________________________________________________________ _ _ */ /* | | | | | */ /* | profile | coordinates for | profile | coordinates for |--> */ /* | 1 | profile 1 | 2 | profile 2 |--> */ /* |_________|___________________|_________|_________________|__ _ _ */ /* */ /* ^ ^ */ /* | | */ /* start of render pool cursor */ /* */ /* The top of the profile stack is kept in the `cursor' variable. */ /* */ /* As you can see, a profile record is pushed on top of the render */ /* pool, which is then followed by its coordinates/intersections. If */ /* a change of direction is detected in the outline, a new profile is */ /* generated until the end of the outline. */ /* */ /* Note that when all profiles have been generated, the function */ /* Finalize_Profile_Table() is used to record, for each profile, its */ /* bottom-most scanline as well as the scanline above its upmost */ /* boundary. These positions are called `extrema' because they (sort */ /* of) correspond to local extrema. They are stored in a sorted list */ /* built from the top of the render pool as a downwards stack: */ /* */ /* _ _ _______________________________________ */ /* | | */ /* <--| sorted list of | */ /* <--| extrema scanlines | */ /* _ _ __________________|____________________| */ /* */ /* ^ ^ */ /* | | */ /* pool_limit end of render pool */ /* */ /* This list is later used during the sweep phase in order to */ /* optimize performance (see technical note on the sweep below). */ /* */ /* Of course, the raster detects whether the two stacks collide and */ /* handles the situation propertly. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* New_Profile */ /* */ /* <Description> */ /* Creates a new Profile in the render pool. */ /* */ /* <Input> */ /* aState :: The state/orientation of the new profile. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult New_Profile( RAS_ARG_ TDirection direction ) { if ( ras.start_prof == NULL ) { ras.cur_prof = (PProfile)ras.cursor; /* current profile */ ras.start_prof = ras.cur_prof; /* first profile in pool */ ras.cursor += AlignProfileSize; /* record profile in buffer */ } /* check for overflow */ if ( ras.cursor >= ras.pool_limit ) { ras.error = ErrRaster_Overflow; return FAILURE; } /* record profile direction */ switch ( direction ) { case Ascending: ras.cur_prof->flow = Flow_Up; break; case Descending: ras.cur_prof->flow = Flow_Down; break; default: ras.error = ErrRaster_Invalid_Map; return FAILURE; } /* initialize a few fields */ { PProfile cur = ras.cur_prof; cur->start = 0; /* current start scanline */ cur->height = 0; /* current height */ cur->offset = ras.cursor; /* address of first coordinate */ cur->link = (PProfile)0; /* link to next profile in pool */ cur->next = (PProfile)0; /* link to next profile in contour */ } /* record the first profile in a contour */ if ( ras.first_prof == NULL ) ras.first_prof = ras.cur_prof; ras.state = direction; ras.fresh = TRUE; /* this profile has no coordinates yet */ ras.joint = FALSE; return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* End_Profile */ /* */ /* <Description> */ /* Finalizes the current Profile and computes its height. If it is */ /* not 0, the profile's fields are updated and a new profile is */ /* pushed on top of its coordinates. Otherwise the current profile */ /* is kept and the recording of intersections is restarted. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult End_Profile( RAS_ARG ) { int h; h = ras.cursor - ras.cur_prof->offset; if ( h < 0 ) { /* This error should _never_ occur unless the raster is buggy */ ras.error = ErrRaster_Negative_Height; return FAILURE; } if ( h > 0 ) { PProfile old, new; /* record scanline height in current profile, create a new one */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -