Index: C:/CartoType/src/main/library/freetype2/src/smooth/ftgrays.c =================================================================== --- C:/CartoType/src/main/library/freetype2/src/smooth/ftgrays.c (revision 1593) +++ C:/CartoType/src/main/library/freetype2/src/smooth/ftgrays.c (working copy) @@ -330,6 +330,8 @@ unsigned char gamma[257]; #endif + int sort_needed; + } TRaster, *PRaster; @@ -404,14 +406,25 @@ PCell cell; if ( !ras.invalid && ( ras.area | ras.cover ) ) { - if ( ras.num_cells >= ras.max_cells ) - return ErrRaster_MemoryOverflow; + if ( ras.sort_needed) + { + if ( ras.num_cells >= ras.max_cells ) + return ErrRaster_MemoryOverflow; - cell = ras.cells + ras.num_cells++; - cell->x = (TCoord)(ras.ex - ras.min_ex); - cell->y = (TCoord)(ras.ey - ras.min_ey); - cell->area = ras.area; - cell->cover = ras.cover; + cell = ras.cells + ras.num_cells++; + cell->x = (TCoord)(ras.ex - ras.min_ex); + cell->y = (TCoord)(ras.ey - ras.min_ey); + cell->area = ras.area; + cell->cover = ras.cover; + } + else + { + cell = ras.cells + (ras.ey - ras.min_ey) * (ras.max_ex - ras.min_ex + 1) + ras.ex - ras.min_ex + 1; + cell->x = ras.ex - ras.min_ex; + cell->y = ras.ey - ras.min_ey; + cell->area += ras.area; + cell->cover += ras.cover; + } } return 0; } @@ -1534,7 +1547,77 @@ } + static void + gray_sweep_if_no_sort_needed( RAS_ARG ) + { + TCoord x, y, cover; + PCell cur, limit; + if ( ras.num_cells == 0 ) + return; + + cur = ras.cells; + limit = cur + ras.num_cells; + + /* Skip leading empty cells. */ + while (cur < limit && cur->cover == 0 && cur->area == 0) + cur++; + if (cur == limit) + return; + + cover = 0; + ras.span_y = -1; + ras.num_gray_spans = 0; + + for (;;) + { + /* if the start cell has a non-null area, we must draw an */ + /* individual gray pixel there */ + x = cur->x; + cover += cur->cover; + if ( cur->area && x >= 0 ) + { + gray_hline( RAS_VAR_ x, cur->y, cover * ( ONE_PIXEL * 2 ) - cur->area, 1 ); + x++; + } + + if ( x < 0 ) + x = 0; + y = cur->y; + cur++; + + /* Skip empty cells. */ + while (cur < limit && cur->cover == 0 && cur->area == 0) + cur++; + + if ( cur < limit && 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; + } + + 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_ /*************************************************************************/ @@ -1883,6 +1966,19 @@ ras.min_ey = band->min; ras.max_ey = band->max; + /* + If the potential maximum number of cells is small enough + we can insert cells directly into the array and skip the sort, + which takes about 50% of rendering time. + */ + + ras.sort_needed = (ras.max_ex - ras.min_ex + 1) * (ras.max_ey - ras.min_ey) > ras.max_cells; + if (!ras.sort_needed) + { + ras.num_cells = (ras.max_ex - ras.min_ex + 1) * (ras.max_ey - ras.min_ey); + memset(ras.cells,0,sizeof(TCell) * ras.num_cells); + } + #if 1 error = gray_convert_glyph_inner( RAS_VAR ); #else @@ -1892,18 +1988,30 @@ if ( !error ) { + if (ras.num_cells) + { + if (ras.sort_needed) + { + #ifdef SHELL_SORT - gray_shell_sort( ras.cells, ras.num_cells ); + gray_shell_sort( ras.cells, ras.num_cells ); #else - gray_quick_sort( ras.cells, ras.num_cells ); + gray_quick_sort( ras.cells, ras.num_cells ); #endif #ifdef DEBUG_GRAYS - gray_check_sort( ras.cells, ras.num_cells ); - gray_dump_cells( RAS_VAR ); + gray_check_sort( ras.cells, ras.num_cells ); + gray_dump_cells( RAS_VAR ); #endif - gray_sweep( RAS_VAR ); + gray_sweep( RAS_VAR ); + } + else + { + gray_sweep_if_no_sort_needed( RAS_VAR ); + } + } + band--; continue; }