📄 ftgrays.c
字号:
raster->cover += delta; ey1 += incr; gray_set_cell( raster, ex, ey1 ); } delta = (int)( fy2 - ONE_PIXEL + first ); raster->area += (TArea)two_fx * delta; raster->cover += delta; goto End; } /* ok, we have to render several scanlines */ p = ( ONE_PIXEL - fy1 ) * dx; first = ONE_PIXEL; incr = 1; if ( dy < 0 ) { p = fy1 * dx; first = 0; incr = -1; dy = -dy; } delta = (int)( p / dy ); mod = (int)( p % dy ); if ( mod < 0 ) { delta--; mod += (TCoord)dy; } x = raster->x + delta; gray_render_scanline( raster, ey1, raster->x, fy1, x, (TCoord)first ); ey1 += incr; gray_set_cell( raster, TRUNC( x ), ey1 ); if ( ey1 != ey2 ) { p = ONE_PIXEL * dx; lift = (int)( p / dy ); rem = (int)( p % dy ); if ( rem < 0 ) { lift--; rem += (int)dy; } mod -= (int)dy; while ( ey1 != ey2 ) { delta = lift; mod += rem; if ( mod >= 0 ) { mod -= (int)dy; delta++; } x2 = x + delta; gray_render_scanline( raster, ey1, x, (TCoord)( ONE_PIXEL - first ), x2, (TCoord)first ); x = x2; ey1 += incr; gray_set_cell( raster, TRUNC( x ), ey1 ); } } gray_render_scanline( raster, ey1, x, (TCoord)( ONE_PIXEL - first ), to_x, fy2 );End: raster->x = to_x; raster->y = to_y; raster->last_ey = SUBPIXELS( ey2 );} static int EVG_Outline_Decompose(EVG_Outline *outline, TRaster *user){ EVG_Vector v_last; EVG_Vector v_start; EVG_Vector* point; EVG_Vector* limit; char* tags; int n; /* index of contour in outline */ int first; /* index of first point in contour */ char tag; /* current point's state */#ifdef INLINE_POINT_CONVERSION TPos _x, _y;#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]; point = outline->points + first; tags = (char*) outline->tags + first; tag = tags[0]; gray_move_to(&v_start, user); while ( point < limit ) { point++; tags++;#ifdef INLINE_POINT_CONVERSION evg_translate_point(user->mx, point, &_x, &_y); gray_render_line(user, _x, _y, 1);#else gray_render_line(user, UPSCALE(point->x), UPSCALE( point->y), 1);#endif }#ifdef INLINE_POINT_CONVERSION evg_translate_point(user->mx, &v_start, &_x, &_y); gray_render_line(user, _x, _y, 0);#else /* close the contour with a line segment */ gray_render_line(user, UPSCALE(v_start.x), UPSCALE( v_start.y), 0);#endif first = last + 1; } return 0;}#define SWAP_CELLS( a, b, temp ) { \ temp = *(a); \ *(a) = *(b); \ *(b) = temp; \ } /* This is a non-recursive quicksort that directly process our cells */ /* array. It should be faster than calling the stdlib qsort(), and we */ /* can even tailor our insertion threshold... */#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */ /* through a normal insertion sort */static void gray_quick_sort( AACell *cells, int count ) { AACell *stack[80]; /* should be enough ;-) */ AACell **top; /* top of stack */ AACell *base, *limit; AACell temp; limit = cells + count; base = cells; top = stack; for (;;) { int len = (int)( limit - base ); AACell *i, *j, *pivot; if ( len > QSORT_THRESHOLD ) { /* we use base + len/2 as the pivot */ pivot = base + len / 2; SWAP_CELLS( base, pivot, temp ); i = base + 1; j = limit - 1; /* now ensure that *i <= *base <= *j */ if(j->x < i->x) SWAP_CELLS( i, j, temp ); if(base->x < i->x) SWAP_CELLS( base, i, temp ); if(j->x < base->x) SWAP_CELLS( base, j, temp ); for (;;) { int x = base->x; do i++; while( i->x < x ); do j--; while( x < j->x ); if ( i > j ) break; SWAP_CELLS( i, j, temp ); } SWAP_CELLS( base, j, temp ); /* now, push the largest sub-array */ if ( j - base > limit - i ) { top[0] = base; top[1] = j; base = i; } else { top[0] = i; top[1] = limit; limit = j; } top += 2; } else { /* the sub-array is small, perform insertion sort */ j = base; i = j + 1; for ( ; i < limit; j = i, i++ ) { for ( ; j[1].x < j->x; j-- ) { SWAP_CELLS( j + 1, j, temp ); if ( j == base ) break; } } if ( top > stack ) { top -= 2; base = top[0]; limit = top[1]; } else break; } }}static void gray_hline( TRaster *raster, TCoord x, TCoord y, TPos area, int acount, Bool zero_non_zero_rule){ EVG_Span* span; int count; int coverage; x += (TCoord)raster->min_ex; if (x>=raster->max_ex) return; y += (TCoord)raster->min_ey; /* 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 (zero_non_zero_rule) { /* normal non-zero winding rule */ if ( coverage >= 256 ) coverage = 255; } else { coverage &= 511; if ( coverage > 256 ) coverage = 512 - coverage; else if ( coverage == 256 ) coverage = 255; } if ( coverage ) { /* see if we can add this span to the current list */ count = raster->num_gray_spans; span = raster->gray_spans + count - 1; if ( count > 0 && (int)span->x + span->len == (int)x && span->coverage == coverage ) { span->len = (unsigned short)( span->len + acount ); return; } if (count >= FT_MAX_GRAY_SPANS ) { raster->render_span(y, count, raster->gray_spans, raster->render_span_data ); raster->num_gray_spans = 0; count = 0; span = raster->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; raster->num_gray_spans++; }}static void gray_sweep_line( TRaster *raster, AAScanline *sl, int y, Bool zero_non_zero_rule){ TCoord x, cover; TArea area; AACell *start, *cur; cur = sl->cells; cover = 0; raster->num_gray_spans = 0; while (sl->num) { start = cur; x = start->x; area = start->area; cover += start->cover; /* accumulate all start cells */ while(--sl->num) { ++cur ; if (cur->x != start->x ) break; area += cur->area; cover += cur->cover; } /* if the start cell has a non-null area, we must draw an */ /* individual gray pixel there */ if ( area && x >= 0 ) { gray_hline( raster, x, y, cover * ( ONE_PIXEL * 2 ) - area, 1, zero_non_zero_rule); x++; } if ( x < 0 ) x = 0; /* draw a gray span between the start cell and the current one */ if ( cur->x > x ) gray_hline( raster, x, y, cover * ( ONE_PIXEL * 2 ), cur->x - x, zero_non_zero_rule); } raster->render_span(y + raster->min_ey, raster->num_gray_spans, raster->gray_spans, raster->render_span_data );}int evg_raster_render(EVG_Raster raster, EVG_Raster_Params* params){ Bool zero_non_zero_rule; int i, size_y; EVG_Outline* outline = (EVG_Outline*)params->source; /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; raster->render_span = (EVG_Raster_Span_Func) params->gray_spans; raster->render_span_data = params->user; /* Set up state in the raster object */ raster->min_ex = params->clip_xMin; raster->min_ey = params->clip_yMin; raster->max_ex = params->clip_xMax; raster->max_ey = params->clip_yMax;#ifdef INLINE_POINT_CONVERSION raster->mx = params->mx;#endif size_y = raster->max_ey - raster->min_ey; if (raster->max_lines < size_y) { raster->scanlines = (AAScanline*)realloc(raster->scanlines, sizeof(AAScanline)*size_y); memset(&raster->scanlines[raster->max_lines], 0, sizeof(AAScanline)*(size_y-raster->max_lines) ); raster->max_lines = size_y; } raster->ex = raster->max_ex+1; raster->ey = raster->max_ey+1; raster->cover = 0; raster->area = 0; EVG_Outline_Decompose(outline, raster); gray_record_cell( raster ); /*store odd/even rule*/ zero_non_zero_rule = (outline->flags & GF_PATH_FILL_ZERO_NONZERO) ? 1 : 0; /* sort each scanline and render it*/ for (i=0; i<size_y; i++) { AAScanline *sl = &raster->scanlines[i]; if (sl->num) { if (sl->num>1) gray_quick_sort(sl->cells, sl->num); gray_sweep_line(raster, sl, i, zero_non_zero_rule); sl->num = 0; } } return 0;}EVG_Raster evg_raster_new(){ TRaster *raster; GF_SAFEALLOC(raster , TRaster); return raster;}void evg_raster_del(EVG_Raster raster){ int i; for (i=0; i<raster->max_lines; i++) { free(raster->scanlines[i].cells); } free(raster->scanlines); free(raster);}/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -