From 80bda804d53e3f0df0ea20c639adc0e479c4ed47 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Thu, 11 Mar 2021 22:40:19 -0500 Subject: [PATCH] [smooth] Reduce copying during integration phase. We now record `cover' and `area' directly into the linked list. This makes rendering faster by 10% or even more at larger sizes. * src/smooth/ftgrays.c (FT_INTEGRATE): Write directly. (gray_TWorker): Add direct cell reference and remove unused fields. (gray_set_cell): Consolidate the linked list management and pointers. (gray_convert_glyph, gray_convert_glyph_inner): Updated. --- ChangeLog | 12 +++++ src/smooth/ftgrays.c | 109 +++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 67 deletions(-) diff --git a/ChangeLog b/ChangeLog index bc4d291af..ef2a65de8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2021-03-11 Alexei Podtelezhnikov + + [smooth] Reduce copying during integration phase. + + We now record `cover' and `area' directly into the linked list. This + makes rendering faster by 10% or even more at larger sizes. + + * src/smooth/ftgrays.c (FT_INTEGRATE): Write directly. + (gray_TWorker): Add direct cell reference and remove unused fields. + (gray_set_cell): Consolidate the linked list management and pointers. + (gray_convert_glyph, gray_convert_glyph_inner): Updated. + 2021-03-10 Alexei Podtelezhnikov * src/smooth/ftgrays.c (FT_INTEGRATE): New convenience macro. diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 5e3d453c6..8ea723028 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -447,14 +447,10 @@ typedef ptrdiff_t FT_PtrDist; { ft_jmp_buf jump_buffer; - TCoord ex, ey; TCoord min_ex, max_ex; TCoord min_ey, max_ey; - TArea area; - TCoord cover; - int invalid; - + PCell cell; PCell* ycells; PCell cells; FT_PtrDist max_cells; @@ -483,8 +479,9 @@ typedef ptrdiff_t FT_PtrDist; static gray_TWorker ras; #endif -#define FT_INTEGRATE( ras, a, b ) \ - ras.cover += (a), ras.area += (a) * (TArea)(b) +#define FT_INTEGRATE( ras, a, b ) \ + if ( ras.cell ) \ + ras.cell->cover += (a), ras.cell->area += (a) * (TArea)(b) typedef struct gray_TRaster_ @@ -521,50 +518,6 @@ typedef ptrdiff_t FT_PtrDist; #endif /* FT_DEBUG_LEVEL_TRACE */ - /************************************************************************** - * - * Record the current cell in the linked list. - */ - static void - gray_record_cell( RAS_ARG ) - { - PCell *pcell, cell; - TCoord x = ras.ex; - - - pcell = &ras.ycells[ras.ey - ras.min_ey]; - while ( ( cell = *pcell ) ) - { - if ( cell->x > x ) - break; - - if ( cell->x == x ) - goto Found; - - pcell = &cell->next; - } - - if ( ras.num_cells >= ras.max_cells ) - ft_longjmp( ras.jump_buffer, 1 ); - - /* insert new cell */ - cell = ras.cells + ras.num_cells++; - cell->x = x; - cell->area = ras.area; - cell->cover = ras.cover; - - cell->next = *pcell; - *pcell = cell; - - return; - - Found: - /* update old cell */ - cell->area += ras.area; - cell->cover += ras.cover; - } - - /************************************************************************** * * Set the current cell to a new position. @@ -573,9 +526,9 @@ typedef ptrdiff_t FT_PtrDist; gray_set_cell( RAS_ARG_ TCoord ex, TCoord ey ) { - /* Move the cell pointer to a new position. We set the `invalid' */ - /* flag to indicate that the cell isn't part of those we're interested */ - /* in during the render phase. This means that: */ + /* Move the cell pointer to a new position in the linked list. We use */ + /* NULL to indicate that the cell is outside of the clipping region */ + /* during the render phase. This means that: */ /* */ /* . the new vertical position must be within min_ey..max_ey-1. */ /* . the new horizontal position must be strictly less than max_ex */ @@ -583,17 +536,42 @@ typedef ptrdiff_t FT_PtrDist; /* Note that if a cell is to the left of the clipping region, it is */ /* actually set to the (min_ex-1) horizontal position. */ - /* record the current one if it is valid and substantial */ - if ( !ras.invalid && ( ras.area || ras.cover ) ) - gray_record_cell( RAS_VAR ); + if ( ey >= ras.max_ey || ey < ras.min_ey || ex >= ras.max_ex ) + ras.cell = NULL; + else + { + PCell *pcell, cell; - ras.area = 0; - ras.cover = 0; - ras.ex = FT_MAX( ex, ras.min_ex - 1 ); - ras.ey = ey; - ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey || - ex >= ras.max_ex ); + ex = FT_MAX( ex, ras.min_ex - 1 ); + + pcell = &ras.ycells[ey - ras.min_ey]; + while ( ( cell = *pcell ) ) + { + if ( cell->x > ex ) + break; + + if ( cell->x == ex ) + goto Found; + + pcell = &cell->next; + } + + if ( ras.num_cells >= ras.max_cells ) + ft_longjmp( ras.jump_buffer, 1 ); + + /* insert new cell */ + cell = ras.cells + ras.num_cells++; + cell->x = ex; + cell->area = 0; + cell->cover = 0; + + cell->next = *pcell; + *pcell = cell; + + Found: + ras.cell = cell; + } } @@ -1631,9 +1609,6 @@ typedef ptrdiff_t FT_PtrDist; if ( continued ) FT_Trace_Enable(); - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - FT_TRACE7(( "band [%d..%d]: %ld cell%s\n", ras.min_ey, ras.max_ey, @@ -1702,7 +1677,7 @@ typedef ptrdiff_t FT_PtrDist; FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) ); ras.num_cells = 0; - ras.invalid = 1; + ras.cell = NULL; ras.min_ey = band[1]; ras.max_ey = band[0];