📄 ftgrays.c
字号:
gray_render_line( RAS_VAR_ mid_x, mid_y ); gray_render_line( RAS_VAR_ to_x, to_y ); return; } arc = ras.bez_stack; arc[0].x = UPSCALE( to->x ); arc[0].y = UPSCALE( to->y ); arc[1].x = UPSCALE( control2->x ); arc[1].y = UPSCALE( control2->y ); arc[2].x = UPSCALE( control1->x ); arc[2].y = UPSCALE( control1->y ); arc[3].x = ras.x; arc[3].y = ras.y; levels = ras.lev_stack; top = 0; levels[0] = level; while ( top >= 0 ) { level = levels[top]; if ( level > 1 ) { /* check that the arc crosses the current band */ TPos min, max, y; min = max = arc[0].y; y = arc[1].y; if ( y < min ) min = y; if ( y > max ) max = y; y = arc[2].y; if ( y < min ) min = y; if ( y > max ) max = y; y = arc[3].y; if ( y < min ) min = y; if ( y > max ) max = y; if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 ) goto Draw; gray_split_cubic( arc ); arc += 3; top ++; levels[top] = levels[top - 1] = level - 1; continue; } Draw: { TPos to_x, to_y, mid_x, mid_y; to_x = arc[0].x; to_y = arc[0].y; mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8; mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8; gray_render_line( RAS_VAR_ mid_x, mid_y ); gray_render_line( RAS_VAR_ to_x, to_y ); top --; arc -= 3; } } return; } static int gray_move_to( const FT_Vector* to, PWorker worker ) { TPos x, y; /* record current cell, if any */ gray_record_cell( worker ); /* start to a new position */ x = UPSCALE( to->x ); y = UPSCALE( to->y ); gray_start_cell( worker, TRUNC( x ), TRUNC( y ) ); worker->x = x; worker->y = y; return 0; } static int gray_line_to( const FT_Vector* to, PWorker worker ) { gray_render_line( worker, UPSCALE( to->x ), UPSCALE( to->y ) ); return 0; } static int gray_conic_to( const FT_Vector* control, const FT_Vector* to, PWorker worker ) { gray_render_conic( worker, control, to ); return 0; } static int gray_cubic_to( const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, PWorker worker ) { gray_render_cubic( worker, control1, control2, to ); return 0; } static void gray_render_span( int y, int count, const FT_Span* spans, PWorker worker ) { unsigned char* p; FT_Bitmap* map = &worker->target; /* first of all, compute the scanline offset */ p = (unsigned char*)map->buffer - y * map->pitch; if ( map->pitch >= 0 ) p += ( map->rows - 1 ) * map->pitch; for ( ; count > 0; count--, spans++ ) { unsigned char coverage = spans->coverage; if ( coverage ) { /* For small-spans it is faster to do it by ourselves than * calling `memset'. This is mainly due to the cost of the * function call. */ if ( spans->len >= 8 ) FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len ); else { unsigned char* q = p + spans->x; switch ( spans->len ) { case 7: *q++ = (unsigned char)coverage; case 6: *q++ = (unsigned char)coverage; case 5: *q++ = (unsigned char)coverage; case 4: *q++ = (unsigned char)coverage; case 3: *q++ = (unsigned char)coverage; case 2: *q++ = (unsigned char)coverage; case 1: *q = (unsigned char)coverage; default: ; } } } } } static void gray_hline( RAS_ARG_ TCoord x, TCoord y, TPos area, int acount ) { FT_Span* span; int count; int coverage; /* compute the coverage line's coverage, depending on the */ /* outline fill rule */ /* */ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ /* */ coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); /* use range 0..256 */ if ( coverage < 0 ) coverage = -coverage; if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) { coverage &= 511; if ( coverage > 256 ) coverage = 512 - coverage; else if ( coverage == 256 ) coverage = 255; } else { /* normal non-zero winding rule */ if ( coverage >= 256 ) coverage = 255; } y += (TCoord)ras.min_ey; x += (TCoord)ras.min_ex; if ( coverage ) { /* see whether we can add this span to the current list */ count = ras.num_gray_spans; span = ras.gray_spans + count - 1; if ( count > 0 && ras.span_y == y && (int)span->x + span->len == (int)x && span->coverage == coverage ) { span->len = (unsigned short)( span->len + acount ); return; } if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) { if ( ras.render_span && count > 0 ) ras.render_span( ras.span_y, count, ras.gray_spans, ras.render_span_data ); /* ras.render_span( span->y, ras.gray_spans, count ); */#ifdef DEBUG_GRAYS if ( ras.span_y >= 0 ) { int n; fprintf( stderr, "y=%3d ", ras.span_y ); span = ras.gray_spans; for ( n = 0; n < count; n++, span++ ) fprintf( stderr, "[%d..%d]:%02x ", span->x, span->x + span->len - 1, span->coverage ); fprintf( stderr, "\n" ); }#endif /* DEBUG_GRAYS */ ras.num_gray_spans = 0; ras.span_y = y; count = 0; span = ras.gray_spans; } else span++; /* add a gray span to the current list */ span->x = (short)x; span->len = (unsigned short)acount; span->coverage = (unsigned char)coverage; ras.num_gray_spans++; } }#ifdef DEBUG_GRAYS /* to be called while in the debugger */ gray_dump_cells( RAS_ARG ) { int yindex; for ( yindex = 0; yindex < ras.ycount; yindex++ ) { PCell cell; printf( "%3d:", yindex ); for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next ) printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area ); printf( "\n" ); } }#endif /* DEBUG_GRAYS */ static void gray_sweep( RAS_ARG_ const FT_Bitmap* target ) { int yindex; FT_UNUSED( target ); if ( ras.num_cells == 0 ) return; ras.num_gray_spans = 0; for ( yindex = 0; yindex < ras.ycount; yindex++ ) { PCell cell = ras.ycells[yindex]; TCoord cover = 0; TCoord x = 0; for ( ; cell != NULL; cell = cell->next ) { TArea area; if ( cell->x > x && cover != 0 ) gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), cell->x - x ); cover += cell->cover; area = cover * ( ONE_PIXEL * 2 ) - cell->area; if ( area != 0 && cell->x >= 0 ) gray_hline( RAS_VAR_ cell->x, yindex, area, 1 ); x = cell->x + 1; } if ( cover != 0 ) gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), ras.count_ex - x ); } if ( ras.render_span && ras.num_gray_spans > 0 ) ras.render_span( ras.span_y, ras.num_gray_spans, ras.gray_spans, ras.render_span_data ); }#ifdef _STANDALONE_ /*************************************************************************/ /* */ /* The following function should only compile in stand_alone mode, */ /* i.e., when building this component without the rest of FreeType. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Decompose */ /* */ /* <Description> */ /* Walks over an outline's structure to decompose it into individual */ /* segments and Bezier arcs. This function is also able to emit */ /* `move to' and `close to' operations to indicate the start and end */ /* of new contours in the outline. */ /* */ /* <Input> */ /* outline :: A pointer to the source target. */ /* */ /* func_interface :: A table of `emitters', i.e,. function pointers */ /* called during decomposition to indicate path */ /* operations. */ /* */ /* user :: A typeless pointer which is passed to each */ /* emitter during the decomposition. It can be */ /* used to store the state during the */ /* decomposition. */ /* */ /* <Return> */ /* Error code. 0 means success. */ /* */ static int FT_Outline_Decompose( const FT_Outline* outline, const FT_Outline_Funcs* func_interface, void* user ) {#undef SCALED#if 0#define SCALED( x ) ( ( (x) << shift ) - delta )#else#define SCALED( x ) (x)#endif FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; FT_Vector* point; FT_Vector* limit; char* tags; int n; /* index of contour in outline */ int first; /* index of first point in contour */ int error; char tag; /* current point's state */#if 0 int shift = func_interface->shift; TPos delta = func_interface->delta;#endif first = 0; for ( n = 0; n < outline->n_contours; n++ ) { int last; /* index of last point in contour */ last = outline->contours[n]; limit = outline->points + last; v_start = outline->points[first]; v_last = outline->points[last]; v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); v_control = v_start; point = outline->points + first; tags = outline->tags + first; tag = FT_CURVE_TAG( tags[0] ); /* A contour cannot start with a cubic control point! */ if ( tag == FT_CURVE_TAG_CUBIC ) goto Invalid_Outline; /* check first point to determine origin */ if ( tag == FT_CURVE_TAG_CONIC ) { /* first point is conic control. Yes, this happens. */ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) { /* start at last point if it is on the curve */ v_start = v_last; limit--; } else { /* if both first and last points are conic, */ /* start at their middle and record its position */ /* for closure */ v_start.x = ( v_start.x + v_last.x ) / 2; v_start.y = ( v_start.y + v_last.y ) / 2; v_last = v_start; } point--; tags--; } error = func_interface->move_to( &v_start, user ); if ( error ) goto Exit; while ( point < limit ) { point++; tags++; tag = FT_CURVE_TAG( tags[0] ); switch ( tag ) { case FT_CURVE_TAG_ON: /* emit a single line_to */ { FT_Vector vec; vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); error = func_interface->line_to( &vec, user ); if ( error ) goto Exit; continue; } case FT_CURVE_TAG_CONIC: /* consume conic arcs */ { v_control.x = SCALED( point->x ); v_control.y = SCALED( point->y ); Do_Conic:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -