📄 qgrayraster.c
字号:
gray_shell_sort ( PCell cells, int count ) { PCell i, j, limit = cells + count; TCell temp; int gap; /* compute initial gap */ for ( gap = 0; ++gap < count; gap *= 3 ) ; while ( gap /= 3 ) { for ( i = cells + gap; i < limit; i++ ) { for ( j = i - gap; ; j -= gap ) { PCell k = j + gap; if ( LESS_THAN( j, k ) ) break; SWAP_CELLS( j, k, temp ); if ( j < cells + gap ) break; } } } }#endif /* SHELL_SORT */#ifdef QUICK_SORT /* 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( PCell cells, int count ) { PCell stack[40]; /* should be enough ;-) */ PCell* top; /* top of stack */ PCell base, limit; TCell temp; limit = cells + count; base = cells; top = stack; for (;;) { int len = (int)( limit - base ); PCell 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 ( LESS_THAN( j, i ) ) SWAP_CELLS( i, j, temp ); if ( LESS_THAN( base, i ) ) SWAP_CELLS( base, i, temp ); if ( LESS_THAN( j, base ) ) SWAP_CELLS( base, j, temp ); for (;;) { do i++; while ( LESS_THAN( i, base ) ); do j--; while ( LESS_THAN( base, j ) ); 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 ( ; LESS_THAN( j + 1, j ); j-- ) { SWAP_CELLS( j + 1, j, temp ); if ( j == base ) break; } } if ( top > stack ) { top -= 2; base = top[0]; limit = top[1]; } else break; } } }#endif /* QUICK_SORT */#ifdef DEBUG_GRAYS#ifdef DEBUG_SORT static int gray_check_sort( PCell cells, int count ) { PCell p, q; for ( p = cells + count - 2; p >= cells; p-- ) { q = p + 1; if ( !LESS_THAN( p, q ) ) return 0; } return 1; }#endif /* DEBUG_SORT */#endif /* DEBUG_GRAYS */ static int gray_move_to( QT_FT_Vector* to, QT_FT_Raster raster ) { TPos x, y; /* record current cell, if any */ gray_record_cell( (PRaster)raster ); /* start to a new position */ x = UPSCALE( to->x ); y = UPSCALE( to->y ); gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); ((PRaster)raster)->x = x; ((PRaster)raster)->y = y; return 0; } static int gray_line_to( QT_FT_Vector* to, QT_FT_Raster raster ) { gray_render_line( (PRaster)raster, UPSCALE( to->x ), UPSCALE( to->y ) ); return 0; } static int gray_conic_to( QT_FT_Vector* control, QT_FT_Vector* to, QT_FT_Raster raster ) { gray_render_conic( (PRaster)raster, control, to ); return 0; } static int gray_cubic_to( QT_FT_Vector* control1, QT_FT_Vector* control2, QT_FT_Vector* to, QT_FT_Raster raster ) { gray_render_cubic( (PRaster)raster, control1, control2, to ); return 0; } static void gray_render_span( int y, int count, QT_FT_Span* spans, PRaster raster ) { unsigned char* p; QT_FT_Bitmap* map = &raster->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;#ifdef GRAYS_USE_GAMMA coverage = raster->gamma[coverage];#endif if ( coverage )#if 1 QT_FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );#else /* 1 */ { q = p + spans->x; limit = q + spans->len; for ( ; q < limit; q++ ) q[0] = (unsigned char)coverage; }#endif /* 1 */ } }#ifdef DEBUG_GRAYS#include <stdio.h> static void gray_dump_cells( RAS_ARG ) { PCell cell, limit; int y = -1; cell = ras.cells; limit = cell + ras.num_cells; for ( ; cell < limit; cell++ ) { if ( cell->y != y ) { fprintf( stderr, "\n%2d: ", cell->y ); y = cell->y; } fprintf( stderr, "[%d %d %d]", cell->x, cell->area, cell->cover ); } fprintf(stderr, "\n" ); }#endif /* DEBUG_GRAYS */ static void gray_hline( RAS_ARG_ TCoord x, TCoord y, TPos area, int acount ) { QT_FT_Span* span; 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 & QT_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 if we can add this span to the current list */ span = ras.gray_spans + ras.num_gray_spans - 1; if ( ras.num_gray_spans > 0 && span->y == y && (int)span->x + span->len == (int)x && span->coverage == coverage ) { span->len = (unsigned short)( span->len + acount ); return; } if ( ras.num_gray_spans >= QT_FT_MAX_GRAY_SPANS ) { if ( ras.render_span ) ras.render_span( ras.num_gray_spans, ras.gray_spans, ras.render_span_data ); /* ras.render_span( span->y, ras.gray_spans, count ); */#ifdef DEBUG_GRAYS if ( 1 ) { int n; fprintf( stderr, "y=%3d ", 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; span = ras.gray_spans; } else span++; /* add a gray span to the current list */ span->x = (short)x; span->len = (unsigned short)acount; span->y = (short)y; span->coverage = (unsigned char)coverage; ras.num_gray_spans++; } } static void gray_sweep( RAS_ARG_ QT_FT_Bitmap* target ) { TCoord x, y, cover; TArea area; PCell start, cur, limit; QT_FT_UNUSED( target ); if ( ras.num_cells == 0 ) return; cur = ras.cells; limit = cur + ras.num_cells; cover = 0; for (;;) { start = cur; y = start->y; x = start->x; area = start->area; cover += start->cover; /* accumulate all start cells */ for (;;) { ++cur; if ( cur >= limit || cur->y != start->y || 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( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 ); x++; } if ( x < 0 ) x = 0; if ( cur < limit && start->y == cur->y ) { /* draw a gray span between the start cell and the current one */ if ( cur->x > x ) gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ), cur->x - x ); } else { /* draw a gray span until the end of the clipping region */ if ( cover && x < ras.max_ex - ras.min_ex ) gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ), (int)( ras.max_ex - x - ras.min_ex ) ); cover = 0; } if ( cur >= limit ) break; }#ifdef DEBUG_GRAYS { int n; QT_FT_Span* span; fprintf( stderr, "y=%3d ", y ); span = ras.gray_spans; for ( n = 0; n < ras.num_gray_spans; n++, span++ ) fprintf( stderr, "[%d..%d]:%02x ", span->x, span->x + span->len - 1, span->coverage ); fprintf( stderr, "\n" ); }#endif /* DEBUG_GRAYS */ } /*************************************************************************/ /* */ /* The following function should only compile in stand_alone mode, */ /* i.e., when building this component without the rest of FreeType. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* QT_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 QT_FT_Outline_Decompose( QT_FT_Outline* outline, const QT_FT_Outline_Funcs* func_interface, void* user ) {#undef SCALED#if 0#define SCALED( x ) ( ( (x) << shift ) - delta )#else#define SCALED( x ) (x)#endif QT_FT_Vector v_last; QT_FT_Vector v_control; QT_FT_Vector v_start; QT_FT_Vector* point; QT_FT_Vector* limit; char* tags; int n; /* index of contour in outline */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -