diff options
Diffstat (limited to 'Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c')
-rw-r--r-- | Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c | 252 |
1 files changed, 131 insertions, 121 deletions
diff --git a/Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c b/Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c index b4cbd3c8eb2..d982c2820b9 100644 --- a/Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c +++ b/Build/source/libs/freetype2/freetype-src/src/smooth/ftgrays.c @@ -149,14 +149,10 @@ #define FT_INT_MAX INT_MAX #define FT_ULONG_MAX ULONG_MAX -#define ADD_LONG( a, b ) \ - (long)( (unsigned long)(a) + (unsigned long)(b) ) -#define SUB_LONG( a, b ) \ - (long)( (unsigned long)(a) - (unsigned long)(b) ) -#define MUL_LONG( a, b ) \ - (long)( (unsigned long)(a) * (unsigned long)(b) ) -#define NEG_LONG( a ) \ - (long)( -(unsigned long)(a) ) +#define ADD_INT( a, b ) \ + (int)( (unsigned int)(a) + (unsigned int)(b) ) + +#define FT_STATIC_BYTE_CAST( type, var ) (type)(unsigned char)(var) #define ft_memset memset @@ -243,10 +239,13 @@ typedef ptrdiff_t FT_PtrDist; #define FT_ERROR( x ) do { } while ( 0 ) /* nothing */ #define FT_THROW( e ) FT_ERR_CAT( Smooth_Err_, e ) - #endif /* !FT_DEBUG_LEVEL_TRACE */ +#define FT_Trace_Enable() do { } while ( 0 ) /* nothing */ +#define FT_Trace_Disable() do { } while ( 0 ) /* nothing */ + + #define FT_DEFINE_OUTLINE_FUNCS( class_, \ move_to_, line_to_, \ conic_to_, cubic_to_, \ @@ -279,6 +278,8 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H #include "ftgrays.h" #include <freetype/internal/ftobjs.h> #include <freetype/internal/ftdebug.h> @@ -359,7 +360,7 @@ typedef ptrdiff_t FT_PtrDist; } \ FT_END_STMNT -#ifdef __arm__ +#if defined( __GNUC__ ) && __GNUC__ < 7 && defined( __arm__ ) /* Work around a bug specific to GCC which make the compiler fail to */ /* optimize a division and modulo operation on the same parameters */ /* into a single call to `__aeabi_idivmod'. See */ @@ -379,14 +380,23 @@ typedef ptrdiff_t FT_PtrDist; #endif /* __arm__ */ - /* These macros speed up repetitive divisions by replacing them */ - /* with multiplications and right shifts. */ -#define FT_UDIVPREP( c, b ) \ - long b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \ - : 0 -#define FT_UDIV( a, b ) \ - (TCoord)( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \ - ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) ) + /* Calculating coverages for a slanted line requires a division each */ + /* time the line crosses from cell to cell. These macros speed up */ + /* the repetitive divisions by replacing them with multiplications */ + /* and right shifts so that at most two divisions are performed for */ + /* each slanted line. Nevertheless, these divisions are noticeable */ + /* in the overall performance because flattened curves produce a */ + /* very large number of slanted lines. */ + /* */ + /* The division results here are always within ONE_PIXEL. Therefore */ + /* the shift magnitude should be at least PIXEL_BITS wider than the */ + /* divisors to provide sufficient accuracy of the multiply-shift. */ + /* It should not exceed (64 - PIXEL_BITS) to prevent overflowing and */ + /* leave enough room for 64-bit unsigned multiplication however. */ +#define FT_UDIVPREP( c, b ) \ + FT_Int64 b ## _r = c ? (FT_Int64)0xFFFFFFFF / ( b ) : 0 +#define FT_UDIV( a, b ) \ + (TCoord)( ( (FT_UInt64)( a ) * (FT_UInt64)( b ## _r ) ) >> 32 ) /* Scale area and apply fill rule to calculate the coverage byte. */ @@ -437,16 +447,17 @@ typedef ptrdiff_t FT_PtrDist; typedef int TCoord; /* integer scanline/pixel coordinate */ typedef int TArea; /* cell areas, coordinate products */ - struct TCell_ + + typedef struct TCell_* PCell; + + typedef struct TCell_ { TCoord x; /* same with gray_TWorker.ex */ TCoord cover; /* same with gray_TWorker.cover */ TArea area; - struct TCell_ *next; - }; + PCell next; - typedef struct TCell_ TCell; - typedef TCell *PCell; + } TCell; typedef struct TPixmap_ { @@ -484,14 +495,11 @@ typedef ptrdiff_t FT_PtrDist; PCell cell; /* current cell */ PCell cell_free; /* call allocation next free slot */ - PCell cell_limit; /* cell allocation limit */ + PCell cell_null; /* last cell, used as dumpster and limit */ PCell* ycells; /* array of cell linked-lists; one per */ /* vertical coordinate in the current band */ - PCell cells; /* cell storage area */ - FT_PtrDist max_cells; /* cell storage capacity */ - TPos x, y; /* last point position */ FT_Outline outline; /* input outline */ @@ -512,25 +520,14 @@ typedef ptrdiff_t FT_PtrDist; static gray_TWorker ras; #endif - /* - * Return a pointer to the 'null cell', used as a sentinel at the end of - * all `ycells` linked lists. Its x coordinate should be maximal to - * ensure no NULL checks are necessary when looking for an insertion point - * in `gray_set_cell`. Other loops should check the cell pointer with - * CELL_IS_NULL() to detect the end of the list. - */ -#define NULL_CELL_PTR( ras ) (ras).cells - /* The |x| value of the null cell. Must be the largest possible */ /* integer value stored in a `TCell.x` field. */ #define CELL_MAX_X_VALUE INT_MAX - /* Return true iff |cell| points to the null cell. */ -#define CELL_IS_NULL( cell ) ( (cell)->x == CELL_MAX_X_VALUE ) - -#define FT_INTEGRATE( ras, a, b ) \ - ras.cell->cover += (a), ras.cell->area += (a) * (TArea)(b) +#define FT_INTEGRATE( ras, a, b ) \ + ras.cell->cover = ADD_INT( ras.cell->cover, a ), \ + ras.cell->area = ADD_INT( ras.cell->area, (a) * (TArea)(b) ) typedef struct gray_TRaster_ @@ -557,7 +554,7 @@ typedef ptrdiff_t FT_PtrDist; printf( "%3d:", y ); - for ( ; !CELL_IS_NULL( cell ); cell = cell->next ) + for ( ; cell != ras.cell_null; cell = cell->next ) printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area ); printf( "\n" ); @@ -576,7 +573,7 @@ typedef ptrdiff_t FT_PtrDist; TCoord ey ) { /* 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 */ + /* a dumpster null cell for everything outside of the clipping region */ /* during the render phase. This means that: */ /* */ /* . the new vertical position must be within min_ey..max_ey-1. */ @@ -589,7 +586,7 @@ typedef ptrdiff_t FT_PtrDist; if ( ey_index < 0 || ey_index >= ras.count_ey || ex >= ras.max_ex ) - ras.cell = NULL_CELL_PTR( ras ); + ras.cell = ras.cell_null; else { PCell* pcell = ras.ycells + ey_index; @@ -613,7 +610,7 @@ typedef ptrdiff_t FT_PtrDist; /* insert new cell */ cell = ras.cell_free++; - if ( cell >= ras.cell_limit ) + if ( cell >= ras.cell_null ) ft_longjmp( ras.jump_buffer, 1 ); cell->x = ex; @@ -629,7 +626,7 @@ typedef ptrdiff_t FT_PtrDist; } -#ifndef FT_LONG64 +#ifndef FT_INT64 /************************************************************************** * @@ -657,8 +654,8 @@ typedef ptrdiff_t FT_PtrDist; return; } - fx1 = FRACT( x1 ); - fx2 = FRACT( x2 ); + fx1 = FRACT( x1 ); + fx2 = FRACT( x2 ); /* everything is located in a single cell. That is easy! */ /* */ @@ -925,7 +922,7 @@ typedef ptrdiff_t FT_PtrDist; } else /* any other line */ { - TPos prod = dx * (TPos)fy1 - dy * (TPos)fx1; + FT_Int64 prod = dx * (FT_Int64)fy1 - dy * (FT_Int64)fx1; FT_UDIVPREP( ex1 != ex2, dx ); FT_UDIVPREP( ey1 != ey2, dy ); @@ -1007,10 +1004,17 @@ typedef ptrdiff_t FT_PtrDist; * * For other cases, using binary splits is actually slightly faster. */ -#if defined( __SSE2__ ) || \ - defined( __x86_64__ ) || \ +#if defined( __SSE2__ ) || \ + defined( __x86_64__ ) || \ + defined( _M_AMD64 ) || \ + ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) +# define FT_SSE2 1 +#else +# define FT_SSE2 0 +#endif + +#if FT_SSE2 || \ defined( __aarch64__ ) || \ - defined( _M_AMD64 ) || \ defined( _M_ARM64 ) # define BEZIER_USE_DDA 1 #else @@ -1019,30 +1023,32 @@ typedef ptrdiff_t FT_PtrDist; /* * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64` - * to be defined. If `FT_LONG64` is not defined, meaning there is no + * to be defined. If `FT_INT64` is not defined, meaning there is no * 64-bit type available, disable it to avoid compilation errors. See for * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071. */ -#if !defined( FT_LONG64 ) +#if !defined( FT_INT64 ) # undef BEZIER_USE_DDA # define BEZIER_USE_DDA 0 #endif #if BEZIER_USE_DDA -#ifdef __SSE2__ +#if FT_SSE2 # include <emmintrin.h> #endif +#define LEFT_SHIFT( a, b ) (FT_Int64)( (FT_UInt64)(a) << (b) ) + + static void gray_render_conic( RAS_ARG_ const FT_Vector* control, const FT_Vector* to ) { FT_Vector p0, p1, p2; - TPos dx, dy; + TPos ax, ay, bx, by, dx, dy; int shift; - FT_Int64 ax, ay, bx, by; FT_Int64 rx, ry; FT_Int64 qx, qy; FT_Int64 px, py; @@ -1070,8 +1076,13 @@ typedef ptrdiff_t FT_PtrDist; return; } - dx = FT_ABS( p0.x + p2.x - 2 * p1.x ); - dy = FT_ABS( p0.y + p2.y - 2 * p1.y ); + bx = p1.x - p0.x; + by = p1.y - p0.y; + ax = p2.x - p1.x - bx; /* p0.x + p2.x - 2 * p1.x */ + ay = p2.y - p1.y - by; /* p0.y + p2.y - 2 * p1.y */ + + dx = FT_ABS( ax ); + dy = FT_ABS( ay ); if ( dx < dy ) dx = dy; @@ -1125,16 +1136,18 @@ typedef ptrdiff_t FT_PtrDist; * EMIT(P) * * To ensure accurate results, perform computations on 64-bit - * values, after scaling them by 2^32: + * values, after scaling them by 2^32. * - * R << 32 = 2 * A << (32 - N - N) - * = A << (33 - 2 *N) + * h = 1 / 2^N * - * Q << 32 = (2 * B << (32 - N)) + (A << (32 - N - N)) - * = (B << (33 - N)) + (A << (32 - N - N)) + * R << 32 = 2 * A << (32 - N - N) + * = A << (33 - 2*N) + * + * Q << 32 = (2 * B << (32 - N)) + (A << (32 - N - N)) + * = (B << (33 - N)) + (A << (32 - 2*N)) */ -#ifdef __SSE2__ +#if FT_SSE2 /* Experience shows that for small shift values, */ /* SSE2 is actually slower. */ if ( shift > 2 ) @@ -1158,10 +1171,10 @@ typedef ptrdiff_t FT_PtrDist; __m128i p; - u.i.ax = p0.x + p2.x - 2 * p1.x; - u.i.ay = p0.y + p2.y - 2 * p1.y; - u.i.bx = p1.x - p0.x; - u.i.by = p1.y - p0.y; + u.i.ax = ax; + u.i.ay = ay; + u.i.bx = bx; + u.i.by = by; a = _mm_load_si128( &u.vec.a ); b = _mm_load_si128( &u.vec.b ); @@ -1179,7 +1192,7 @@ typedef ptrdiff_t FT_PtrDist; p = _mm_load_si128( &v.vec ); - for ( count = ( 1U << shift ); count > 0; count-- ) + for ( count = 1U << shift; count > 0; count-- ) { p = _mm_add_epi64( p, q ); q = _mm_add_epi64( q, r ); @@ -1191,21 +1204,16 @@ typedef ptrdiff_t FT_PtrDist; return; } -#endif /* __SSE2__ */ +#endif /* FT_SSE2 */ - ax = p0.x + p2.x - 2 * p1.x; - ay = p0.y + p2.y - 2 * p1.y; - bx = p1.x - p0.x; - by = p1.y - p0.y; - - rx = ax << ( 33 - 2 * shift ); - ry = ay << ( 33 - 2 * shift ); + rx = LEFT_SHIFT( ax, 33 - 2 * shift ); + ry = LEFT_SHIFT( ay, 33 - 2 * shift ); - qx = ( bx << ( 33 - shift ) ) + ( ax << ( 32 - 2 * shift ) ); - qy = ( by << ( 33 - shift ) ) + ( ay << ( 32 - 2 * shift ) ); + qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift ); + qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift ); - px = (FT_Int64)p0.x << 32; - py = (FT_Int64)p0.y << 32; + px = LEFT_SHIFT( p0.x, 32 ); + py = LEFT_SHIFT( p0.y, 32 ); for ( count = 1U << shift; count > 0; count-- ) { @@ -1255,7 +1263,7 @@ typedef ptrdiff_t FT_PtrDist; FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */ FT_Vector* arc = bez_stack; TPos dx, dy; - int draw, split; + int draw; arc[0].x = UPSCALE( to->x ); @@ -1298,7 +1306,9 @@ typedef ptrdiff_t FT_PtrDist; /* many times as there are trailing zeros in the counter. */ do { - split = draw & ( -draw ); /* isolate the rightmost 1-bit */ + int split = draw & ( -draw ); /* isolate the rightmost 1-bit */ + + while ( ( split >>= 1 ) ) { gray_split_conic( arc ); @@ -1465,7 +1475,8 @@ typedef ptrdiff_t FT_PtrDist; static void gray_sweep( RAS_ARG ) { - int fill = ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ? 0x100 : INT_MIN; + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; int coverage; int y; @@ -1475,13 +1486,15 @@ typedef ptrdiff_t FT_PtrDist; PCell cell = ras.ycells[y - ras.min_ey]; TCoord x = ras.min_ex; TArea cover = 0; - TArea area; unsigned char* line = ras.target.origin - ras.target.pitch * y; - for ( ; !CELL_IS_NULL( cell ); cell = cell->next ) + for ( ; cell != ras.cell_null; cell = cell->next ) { + TArea area; + + if ( cover != 0 && cell->x > x ) { FT_FILL_RULE( coverage, cover, fill ); @@ -1512,7 +1525,8 @@ typedef ptrdiff_t FT_PtrDist; static void gray_sweep_direct( RAS_ARG ) { - int fill = ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ? 0x100 : INT_MIN; + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; int coverage; int y; @@ -1525,11 +1539,13 @@ typedef ptrdiff_t FT_PtrDist; PCell cell = ras.ycells[y - ras.min_ey]; TCoord x = ras.min_ex; TArea cover = 0; - TArea area; - for ( ; !CELL_IS_NULL( cell ); cell = cell->next ) + for ( ; cell != ras.cell_null; cell = cell->next ) { + TArea area; + + if ( cover != 0 && cell->x > x ) { FT_FILL_RULE( coverage, cover, fill ); @@ -1905,11 +1921,11 @@ typedef ptrdiff_t FT_PtrDist; if ( continued ) FT_Trace_Enable(); - FT_TRACE7(( "band [%d..%d]: %ld cell%s\n", + FT_TRACE7(( "band [%d..%d]: %ld cell%s remaining/\n", ras.min_ey, ras.max_ey, - ras.cell_free - ras.cells, - ras.cell_free - ras.cells == 1 ? "" : "s" )); + ras.cell_null - ras.cell_free, + ras.cell_null - ras.cell_free == 1 ? "" : "s" )); } else { @@ -1937,9 +1953,18 @@ typedef ptrdiff_t FT_PtrDist; TCoord* band; int continued = 0; - PCell null_cell; + + + /* Initialize the null cell at the end of the poll. */ + ras.cell_null = buffer + FT_MAX_GRAY_POOL - 1; + ras.cell_null->x = CELL_MAX_X_VALUE; + ras.cell_null->area = 0; + ras.cell_null->cover = 0; + ras.cell_null->next = NULL; /* set up vertical bands */ + ras.ycells = (PCell*)buffer; + if ( height > n ) { /* two divisions rounded up */ @@ -1947,23 +1972,6 @@ typedef ptrdiff_t FT_PtrDist; height = ( height + n - 1 ) / n; } - /* memory management */ - n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell ); - - ras.cells = buffer + n; - ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n ); - ras.cell_limit = ras.cells + ras.max_cells; - ras.ycells = (PCell*)buffer; - - /* Initialize the null cell at the start of the `cells` array. */ - /* Note that this requires `ras.cell_free` initialization to skip */ - /* over the first entry in the array. */ - null_cell = NULL_CELL_PTR( ras ); - null_cell->x = CELL_MAX_X_VALUE; - null_cell->area = 0; - null_cell->cover = 0; - null_cell->next = NULL;; - for ( y = yMin; y < yMax; ) { ras.min_ey = y; @@ -1982,10 +1990,14 @@ typedef ptrdiff_t FT_PtrDist; for ( w = 0; w < width; ++w ) - ras.ycells[w] = null_cell; + ras.ycells[w] = ras.cell_null; - ras.cell_free = ras.cells + 1; /* NOTE: Skip over the null cell. */ - ras.cell = null_cell; + /* memory management: skip ycells */ + n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / + sizeof ( TCell ); + + ras.cell_free = buffer + n; + ras.cell = ras.cell_null; ras.min_ey = band[1]; ras.max_ey = band[0]; ras.count_ey = width; @@ -2142,19 +2154,17 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ static int - gray_raster_new( FT_Memory memory, - FT_Raster* araster ) + gray_raster_new( FT_Memory memory, + gray_PRaster* araster ) { FT_Error error; gray_PRaster raster = NULL; - *araster = 0; - if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) ) - { + if ( !FT_NEW( raster ) ) raster->memory = memory; - *araster = (FT_Raster)raster; - } + + *araster = raster; return error; } |