summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/smooth
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/smooth')
-rw-r--r--src/3rdparty/freetype/src/smooth/Jamfile32
-rw-r--r--src/3rdparty/freetype/src/smooth/ftgrays.c882
-rw-r--r--src/3rdparty/freetype/src/smooth/ftgrays.h4
-rw-r--r--src/3rdparty/freetype/src/smooth/ftsmerrs.h6
-rw-r--r--src/3rdparty/freetype/src/smooth/ftsmooth.c712
-rw-r--r--src/3rdparty/freetype/src/smooth/ftsmooth.h9
-rw-r--r--src/3rdparty/freetype/src/smooth/ftspic.c118
-rw-r--r--src/3rdparty/freetype/src/smooth/ftspic.h75
-rw-r--r--src/3rdparty/freetype/src/smooth/module.mk6
-rw-r--r--src/3rdparty/freetype/src/smooth/rules.mk2
-rw-r--r--src/3rdparty/freetype/src/smooth/smooth.c3
11 files changed, 1006 insertions, 843 deletions
diff --git a/src/3rdparty/freetype/src/smooth/Jamfile b/src/3rdparty/freetype/src/smooth/Jamfile
deleted file mode 100644
index 6ca1cede9e..0000000000
--- a/src/3rdparty/freetype/src/smooth/Jamfile
+++ /dev/null
@@ -1,32 +0,0 @@
-# FreeType 2 src/smooth Jamfile
-#
-# Copyright (C) 2001-2019 by
-# David Turner, Robert Wilhelm, and Werner Lemberg.
-#
-# This file is part of the FreeType project, and may only be used, modified,
-# and distributed under the terms of the FreeType project license,
-# LICENSE.TXT. By continuing to use, modify, or distribute this file you
-# indicate that you have read the license and understand and accept it
-# fully.
-
-SubDir FT2_TOP $(FT2_SRC_DIR) smooth ;
-
-{
- local _sources ;
-
- if $(FT2_MULTI)
- {
- _sources = ftgrays
- ftsmooth
- ftspic
- ;
- }
- else
- {
- _sources = smooth ;
- }
-
- Library $(FT2_LIB) : $(_sources).c ;
-}
-
-# end of src/smooth Jamfile
diff --git a/src/3rdparty/freetype/src/smooth/ftgrays.c b/src/3rdparty/freetype/src/smooth/ftgrays.c
index fd357a50fc..0918272f87 100644
--- a/src/3rdparty/freetype/src/smooth/ftgrays.c
+++ b/src/3rdparty/freetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
*
* A new `perfect' anti-aliasing renderer (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -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
@@ -168,10 +164,11 @@
typedef ptrdiff_t FT_PtrDist;
-#define ErrRaster_Invalid_Mode -2
-#define ErrRaster_Invalid_Outline -1
-#define ErrRaster_Invalid_Argument -3
-#define ErrRaster_Memory_Overflow -4
+#define Smooth_Err_Ok 0
+#define Smooth_Err_Invalid_Outline -1
+#define Smooth_Err_Cannot_Render_Glyph -2
+#define Smooth_Err_Invalid_Argument -3
+#define Smooth_Err_Raster_Overflow -4
#define FT_BEGIN_HEADER
#define FT_END_HEADER
@@ -229,23 +226,26 @@ typedef ptrdiff_t FT_PtrDist;
#define FT_ERROR( varformat ) FT_Message varformat
#endif
-#define FT_THROW( e ) \
- ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ), \
- __LINE__, \
- __FILE__ ) | \
- FT_ERR_CAT( ErrRaster_, e ) )
+#define FT_THROW( e ) \
+ ( FT_Throw( FT_ERR_CAT( Smooth_Err_, e ), \
+ __LINE__, \
+ __FILE__ ) | \
+ FT_ERR_CAT( Smooth_Err_, e ) )
#else /* !FT_DEBUG_LEVEL_TRACE */
#define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
-#define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e )
-
+#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,18 +279,15 @@ typedef ptrdiff_t FT_PtrDist;
#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
#include "ftgrays.h"
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_OUTLINE_H
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/ftoutln.h>
#include "ftsmerrs.h"
-#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
-#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory
-#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
-
#endif /* !STANDALONE_ */
@@ -336,7 +333,9 @@ typedef ptrdiff_t FT_PtrDist;
#define PIXEL_BITS 8
#define ONE_PIXEL ( 1 << PIXEL_BITS )
+#undef TRUNC
#define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS )
+#undef FRACT
#define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) )
#if PIXEL_BITS >= 6
@@ -363,7 +362,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 */
@@ -383,14 +382,58 @@ 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. */
+ /* The top fill bit is used for the non-zero rule. The eighth */
+ /* fill bit is used for the even-odd rule. The higher coverage */
+ /* bytes are either clamped for the non-zero-rule or discarded */
+ /* later for the even-odd rule. */
+#define FT_FILL_RULE( coverage, area, fill ) \
+ FT_BEGIN_STMNT \
+ coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); \
+ if ( coverage & fill ) \
+ coverage = ~coverage; \
+ if ( coverage > 255 && fill & INT_MIN ) \
+ coverage = 255; \
+ FT_END_STMNT
+
+
+ /* It is faster to write small spans byte-by-byte than calling */
+ /* `memset'. This is mainly due to the cost of the function call. */
+#define FT_GRAY_SET( d, s, count ) \
+ FT_BEGIN_STMNT \
+ unsigned char* q = d; \
+ switch ( count ) \
+ { \
+ case 7: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 6: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 5: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 4: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 3: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 2: *q++ = (unsigned char)s; FALL_THROUGH; \
+ case 1: *q = (unsigned char)s; FALL_THROUGH; \
+ case 0: break; \
+ default: FT_MEM_SET( d, s, count ); \
+ } \
+ FT_END_STMNT
/**************************************************************************
@@ -433,7 +476,7 @@ typedef ptrdiff_t FT_PtrDist;
#endif
/* FT_Span buffer size for direct rendering only */
-#define FT_MAX_GRAY_SPANS 10
+#define FT_MAX_GRAY_SPANS 16
#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
@@ -448,28 +491,24 @@ typedef ptrdiff_t FT_PtrDist;
{
ft_jmp_buf jump_buffer;
- TCoord ex, ey;
- TCoord min_ex, max_ex;
+ TCoord min_ex, max_ex; /* min and max integer pixel coordinates */
TCoord min_ey, max_ey;
+ TCoord count_ey; /* same as (max_ey - min_ey) */
- TArea area;
- TCoord cover;
- int invalid;
+ PCell cell; /* current cell */
+ PCell cell_free; /* call allocation next free slot */
+ PCell cell_null; /* last cell, used as dumpster and limit */
- PCell* ycells;
- PCell cells;
- FT_PtrDist max_cells;
- FT_PtrDist num_cells;
+ PCell* ycells; /* array of cell linked-lists; one per */
+ /* vertical coordinate in the current band */
- TPos x, y;
+ TPos x, y; /* last point position */
- FT_Outline outline;
- TPixmap target;
+ FT_Outline outline; /* input outline */
+ TPixmap target; /* target pixmap */
FT_Raster_Span_Func render_span;
void* render_span_data;
- FT_Span spans[FT_MAX_GRAY_SPANS];
- int num_spans;
} gray_TWorker, *gray_PWorker;
@@ -477,17 +516,25 @@ typedef ptrdiff_t FT_PtrDist;
#pragma warning( pop )
#endif
-
#ifndef FT_STATIC_RASTER
#define ras (*worker)
#else
static gray_TWorker ras;
#endif
+ /* 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
+
+
+#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_
{
- void* memory;
+ void* memory;
} gray_TRaster, *gray_PRaster;
@@ -509,7 +556,7 @@ typedef ptrdiff_t FT_PtrDist;
printf( "%3d:", y );
- for ( ; cell != NULL; 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" );
@@ -521,81 +568,67 @@ typedef ptrdiff_t FT_PtrDist;
/**************************************************************************
*
- * Record the current cell in the linked list.
+ * Set the current cell to a new position.
*/
static void
- gray_record_cell( RAS_ARG )
+ gray_set_cell( RAS_ARG_ TCoord ex,
+ TCoord ey )
{
- PCell *pcell, cell;
- TCoord x = ras.ex;
-
+ /* Move the cell pointer to a new position in the linked list. We use */
+ /* 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. */
+ /* . the new horizontal position must be strictly less than max_ex */
+ /* */
+ /* Note that if a cell is to the left of the clipping region, it is */
+ /* actually set to the (min_ex-1) horizontal position. */
- pcell = &ras.ycells[ras.ey - ras.min_ey];
- while ( ( cell = *pcell ) )
- {
- if ( cell->x > x )
- break;
+ TCoord ey_index = ey - ras.min_ey;
- if ( cell->x == x )
- goto Found;
- pcell = &cell->next;
- }
+ if ( ey_index < 0 || ey_index >= ras.count_ey || ex >= ras.max_ex )
+ ras.cell = ras.cell_null;
+ else
+ {
+ PCell* pcell = ras.ycells + ey_index;
+ PCell cell;
- 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;
+ ex = FT_MAX( ex, ras.min_ex - 1 );
- cell->next = *pcell;
- *pcell = cell;
+ while ( 1 )
+ {
+ cell = *pcell;
- return;
+ if ( cell->x > ex )
+ break;
- Found:
- /* update old cell */
- cell->area += ras.area;
- cell->cover += ras.cover;
- }
+ if ( cell->x == ex )
+ goto Found;
+ pcell = &cell->next;
+ }
- /**************************************************************************
- *
- * Set the current cell to a new position.
- */
- static void
- 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: */
- /* */
- /* . the new vertical position must be within min_ey..max_ey-1. */
- /* . the new horizontal position must be strictly less than max_ex */
- /* */
- /* Note that if a cell is to the left of the clipping region, it is */
- /* actually set to the (min_ex-1) horizontal position. */
+ /* insert new cell */
+ cell = ras.cell_free++;
+ if ( cell >= ras.cell_null )
+ ft_longjmp( ras.jump_buffer, 1 );
- /* record the current one if it is valid and substantial */
- if ( !ras.invalid && ( ras.area || ras.cover ) )
- gray_record_cell( RAS_VAR );
+ cell->x = ex;
+ cell->area = 0;
+ cell->cover = 0;
- ras.area = 0;
- ras.cover = 0;
- ras.ex = FT_MAX( ex, ras.min_ex - 1 );
- ras.ey = ey;
+ cell->next = *pcell;
+ *pcell = cell;
- ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
- ex >= ras.max_ex );
+ Found:
+ ras.cell = cell;
+ }
}
-#ifndef FT_LONG64
+#ifndef FT_INT64
/**************************************************************************
*
@@ -623,8 +656,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! */
/* */
@@ -656,10 +689,9 @@ typedef ptrdiff_t FT_PtrDist;
/* XXX: y-delta and x-delta below should be related. */
FT_DIV_MOD( TCoord, p, dx, delta, mod );
- ras.area += (TArea)( ( fx1 + first ) * delta );
- ras.cover += delta;
- y1 += delta;
- ex1 += incr;
+ FT_INTEGRATE( ras, delta, fx1 + first );
+ y1 += delta;
+ ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
if ( ex1 != ex2 )
@@ -680,10 +712,9 @@ typedef ptrdiff_t FT_PtrDist;
delta++;
}
- ras.area += (TArea)( ONE_PIXEL * delta );
- ras.cover += delta;
- y1 += delta;
- ex1 += incr;
+ FT_INTEGRATE( ras, delta, ONE_PIXEL );
+ y1 += delta;
+ ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
} while ( ex1 != ex2 );
}
@@ -691,10 +722,7 @@ typedef ptrdiff_t FT_PtrDist;
fx1 = ONE_PIXEL - first;
End:
- dy = y2 - y1;
-
- ras.area += (TArea)( ( fx1 + fx2 ) * dy );
- ras.cover += dy;
+ FT_INTEGRATE( ras, y2 - y1, fx1 + fx2 );
}
@@ -737,7 +765,6 @@ typedef ptrdiff_t FT_PtrDist;
{
TCoord ex = TRUNC( ras.x );
TCoord two_fx = FRACT( ras.x ) << 1;
- TArea area;
if ( dy > 0)
@@ -751,27 +778,23 @@ typedef ptrdiff_t FT_PtrDist;
incr = -1;
}
- delta = first - fy1;
- ras.area += (TArea)two_fx * delta;
- ras.cover += delta;
- ey1 += incr;
+ delta = first - fy1;
+ FT_INTEGRATE( ras, delta, two_fx);
+ ey1 += incr;
gray_set_cell( RAS_VAR_ ex, ey1 );
delta = first + first - ONE_PIXEL;
- area = (TArea)two_fx * delta;
while ( ey1 != ey2 )
{
- ras.area += area;
- ras.cover += delta;
- ey1 += incr;
+ FT_INTEGRATE( ras, delta, two_fx);
+ ey1 += incr;
gray_set_cell( RAS_VAR_ ex, ey1 );
}
- delta = fy2 - ONE_PIXEL + first;
- ras.area += (TArea)two_fx * delta;
- ras.cover += delta;
+ delta = fy2 - ONE_PIXEL + first;
+ FT_INTEGRATE( ras, delta, two_fx);
goto End;
}
@@ -884,8 +907,7 @@ typedef ptrdiff_t FT_PtrDist;
do
{
fy2 = ONE_PIXEL;
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 );
fy1 = 0;
ey1++;
gray_set_cell( RAS_VAR_ ex1, ey1 );
@@ -894,8 +916,7 @@ typedef ptrdiff_t FT_PtrDist;
do
{
fy2 = 0;
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 );
fy1 = ONE_PIXEL;
ey1--;
gray_set_cell( RAS_VAR_ ex1, ey1 );
@@ -903,7 +924,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 );
@@ -913,72 +934,309 @@ typedef ptrdiff_t FT_PtrDist;
/* also easily updated when moving from one cell to the next. */
do
{
- if ( prod <= 0 &&
- prod - dx * ONE_PIXEL > 0 ) /* left */
+ if ( prod - dx * ONE_PIXEL > 0 &&
+ prod <= 0 ) /* left */
{
fx2 = 0;
fy2 = FT_UDIV( -prod, -dx );
prod -= dy * ONE_PIXEL;
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
fx1 = ONE_PIXEL;
fy1 = fy2;
ex1--;
}
- else if ( prod - dx * ONE_PIXEL <= 0 &&
- prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
+ else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 &&
+ prod - dx * ONE_PIXEL <= 0 ) /* up */
{
prod -= dx * ONE_PIXEL;
fx2 = FT_UDIV( -prod, dy );
fy2 = ONE_PIXEL;
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
fx1 = fx2;
fy1 = 0;
ey1++;
}
- else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
- prod + dy * ONE_PIXEL >= 0 ) /* right */
+ else if ( prod + dy * ONE_PIXEL >= 0 &&
+ prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 ) /* right */
{
prod += dy * ONE_PIXEL;
fx2 = ONE_PIXEL;
fy2 = FT_UDIV( prod, dx );
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
fx1 = 0;
fy1 = fy2;
ex1++;
}
- else /* ( prod + dy * ONE_PIXEL < 0 &&
- prod > 0 ) down */
+ else /* ( prod > 0 &&
+ prod + dy * ONE_PIXEL < 0 ) down */
{
fx2 = FT_UDIV( prod, -dy );
fy2 = 0;
prod += dx * ONE_PIXEL;
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
fx1 = fx2;
fy1 = ONE_PIXEL;
ey1--;
}
gray_set_cell( RAS_VAR_ ex1, ey1 );
+
} while ( ex1 != ex2 || ey1 != ey2 );
}
fx2 = FRACT( to_x );
fy2 = FRACT( to_y );
- ras.cover += ( fy2 - fy1 );
- ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
End:
- ras.x = to_x;
- ras.y = to_y;
+ ras.x = to_x;
+ ras.y = to_y;
}
#endif
+ /*
+ * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
+ * is slightly faster in the following cases:
+ *
+ * - When the host CPU is 64-bit.
+ * - When SSE2 SIMD registers and instructions are available (even on
+ * x86).
+ *
+ * For other cases, using binary splits is actually slightly faster.
+ */
+#if ( defined( __SSE2__ ) || \
+ defined( __x86_64__ ) || \
+ defined( _M_AMD64 ) || \
+ ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
+ !defined( __VMS )
+# define FT_SSE2 1
+#else
+# define FT_SSE2 0
+#endif
+
+#if FT_SSE2 || \
+ defined( __aarch64__ ) || \
+ defined( _M_ARM64 )
+# define BEZIER_USE_DDA 1
+#else
+# define BEZIER_USE_DDA 0
+#endif
+
+ /*
+ * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
+ * 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_INT64 )
+# undef BEZIER_USE_DDA
+# define BEZIER_USE_DDA 0
+#endif
+
+#if BEZIER_USE_DDA
+
+#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 ax, ay, bx, by, dx, dy;
+ int shift;
+
+ FT_Int64 rx, ry;
+ FT_Int64 qx, qy;
+ FT_Int64 px, py;
+
+ FT_UInt count;
+
+
+ p0.x = ras.x;
+ p0.y = ras.y;
+ p1.x = UPSCALE( control->x );
+ p1.y = UPSCALE( control->y );
+ p2.x = UPSCALE( to->x );
+ p2.y = UPSCALE( to->y );
+
+ /* short-cut the arc that crosses the current band */
+ if ( ( TRUNC( p0.y ) >= ras.max_ey &&
+ TRUNC( p1.y ) >= ras.max_ey &&
+ TRUNC( p2.y ) >= ras.max_ey ) ||
+ ( TRUNC( p0.y ) < ras.min_ey &&
+ TRUNC( p1.y ) < ras.min_ey &&
+ TRUNC( p2.y ) < ras.min_ey ) )
+ {
+ ras.x = p2.x;
+ ras.y = p2.y;
+ return;
+ }
+
+ 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;
+
+ if ( dx <= ONE_PIXEL / 4 )
+ {
+ gray_render_line( RAS_VAR_ p2.x, p2.y );
+ return;
+ }
+
+ /* We can calculate the number of necessary bisections because */
+ /* each bisection predictably reduces deviation exactly 4-fold. */
+ /* Even 32-bit deviation would vanish after 16 bisections. */
+ shift = 0;
+ do
+ {
+ dx >>= 2;
+ shift += 1;
+
+ } while ( dx > ONE_PIXEL / 4 );
+
+ /*
+ * The (P0,P1,P2) arc equation, for t in [0,1] range:
+ *
+ * P(t) = P0*(1-t)^2 + P1*2*t*(1-t) + P2*t^2
+ *
+ * P(t) = P0 + 2*(P1-P0)*t + (P0+P2-2*P1)*t^2
+ * = P0 + 2*B*t + A*t^2
+ *
+ * for A = P0 + P2 - 2*P1
+ * and B = P1 - P0
+ *
+ * Let's consider the difference when advancing by a small
+ * parameter h:
+ *
+ * Q(h,t) = P(t+h) - P(t) = 2*B*h + A*h^2 + 2*A*h*t
+ *
+ * And then its own difference:
+ *
+ * R(h,t) = Q(h,t+h) - Q(h,t) = 2*A*h*h = R (constant)
+ *
+ * Since R is always a constant, it is possible to compute
+ * successive positions with:
+ *
+ * P = P0
+ * Q = Q(h,0) = 2*B*h + A*h*h
+ * R = 2*A*h*h
+ *
+ * loop:
+ * P += Q
+ * Q += R
+ * EMIT(P)
+ *
+ * To ensure accurate results, perform computations on 64-bit
+ * values, after scaling them by 2^32.
+ *
+ * h = 1 / 2^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))
+ */
+
+#if FT_SSE2
+ /* Experience shows that for small shift values, */
+ /* SSE2 is actually slower. */
+ if ( shift > 2 )
+ {
+ union
+ {
+ struct { FT_Int64 ax, ay, bx, by; } i;
+ struct { __m128i a, b; } vec;
+
+ } u;
+
+ union
+ {
+ struct { FT_Int32 px_lo, px_hi, py_lo, py_hi; } i;
+ __m128i vec;
+
+ } v;
+
+ __m128i a, b;
+ __m128i r, q, q2;
+ __m128i p;
+
+
+ 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 );
+
+ r = _mm_slli_epi64( a, 33 - 2 * shift );
+ q = _mm_slli_epi64( b, 33 - shift );
+ q2 = _mm_slli_epi64( a, 32 - 2 * shift );
+
+ q = _mm_add_epi64( q2, q );
+
+ v.i.px_lo = 0;
+ v.i.px_hi = p0.x;
+ v.i.py_lo = 0;
+ v.i.py_hi = p0.y;
+
+ p = _mm_load_si128( &v.vec );
+
+ for ( count = 1U << shift; count > 0; count-- )
+ {
+ p = _mm_add_epi64( p, q );
+ q = _mm_add_epi64( q, r );
+
+ _mm_store_si128( &v.vec, p );
+
+ gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
+ }
+
+ return;
+ }
+#endif /* FT_SSE2 */
+
+ rx = LEFT_SHIFT( ax, 33 - 2 * shift );
+ ry = LEFT_SHIFT( ay, 33 - 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 = LEFT_SHIFT( p0.x, 32 );
+ py = LEFT_SHIFT( p0.y, 32 );
+
+ for ( count = 1U << shift; count > 0; count-- )
+ {
+ px += qx;
+ py += qy;
+ qx += rx;
+ qy += ry;
+
+ gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
+ (FT_Pos)( py >> 32 ) );
+ }
+ }
+
+#else /* !BEZIER_USE_DDA */
+
+ /*
+ * Note that multiple attempts to speed up the function below
+ * with SSE2 intrinsics, using various data layouts, have turned
+ * out to be slower than the non-SIMD code below.
+ */
static void
gray_split_conic( FT_Vector* base )
{
@@ -1008,7 +1266,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 );
@@ -1051,7 +1309,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 );
@@ -1064,7 +1324,17 @@ typedef ptrdiff_t FT_PtrDist;
} while ( --draw );
}
+#endif /* !BEZIER_USE_DDA */
+
+ /*
+ * For cubic Bézier, binary splits are still faster than DDA
+ * because the splits are adaptive to how quickly each sub-arc
+ * approaches their chord trisection points.
+ *
+ * It might be useful to experiment with SSE2 to speed up
+ * `gray_split_cubic`, though.
+ */
static void
gray_split_cubic( FT_Vector* base )
{
@@ -1158,8 +1428,10 @@ typedef ptrdiff_t FT_PtrDist;
static int
gray_move_to( const FT_Vector* to,
- gray_PWorker worker )
+ void* worker_ ) /* gray_PWorker */
{
+ gray_PWorker worker = (gray_PWorker)worker_;
+
TPos x, y;
@@ -1177,8 +1449,11 @@ typedef ptrdiff_t FT_PtrDist;
static int
gray_line_to( const FT_Vector* to,
- gray_PWorker worker )
+ void* worker_ ) /* gray_PWorker */
{
+ gray_PWorker worker = (gray_PWorker)worker_;
+
+
gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
return 0;
}
@@ -1187,8 +1462,11 @@ typedef ptrdiff_t FT_PtrDist;
static int
gray_conic_to( const FT_Vector* control,
const FT_Vector* to,
- gray_PWorker worker )
+ void* worker_ ) /* gray_PWorker */
{
+ gray_PWorker worker = (gray_PWorker)worker_;
+
+
gray_render_conic( RAS_VAR_ control, to );
return 0;
}
@@ -1198,133 +1476,144 @@ typedef ptrdiff_t FT_PtrDist;
gray_cubic_to( const FT_Vector* control1,
const FT_Vector* control2,
const FT_Vector* to,
- gray_PWorker worker )
+ void* worker_ ) /* gray_PWorker */
{
+ gray_PWorker worker = (gray_PWorker)worker_;
+
+
gray_render_cubic( RAS_VAR_ control1, control2, to );
return 0;
}
static void
- gray_hline( RAS_ARG_ TCoord x,
- TCoord y,
- TArea coverage,
- TCoord acount )
+ gray_sweep( RAS_ARG )
{
- /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */
- coverage >>= PIXEL_BITS * 2 + 1 - 8;
+ int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+ : INT_MIN;
+ int coverage;
+ int y;
- /* compute the line's coverage depending on the outline fill rule */
- if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
- {
- coverage &= 511;
- if ( coverage >= 256 )
- coverage = 511 - coverage;
- }
- else /* default non-zero winding rule */
+ for ( y = ras.min_ey; y < ras.max_ey; y++ )
{
- if ( coverage < 0 )
- coverage = ~coverage; /* the same as -coverage - 1 */
+ PCell cell = ras.ycells[y - ras.min_ey];
+ TCoord x = ras.min_ex;
+ TArea cover = 0;
- if ( coverage >= 256 )
- coverage = 255;
- }
+ unsigned char* line = ras.target.origin - ras.target.pitch * y;
- if ( ras.num_spans >= 0 ) /* for FT_RASTER_FLAG_DIRECT only */
- {
- FT_Span* span = ras.spans + ras.num_spans++;
+ for ( ; cell != ras.cell_null; cell = cell->next )
+ {
+ TArea area;
- span->x = (short)x;
- span->len = (unsigned short)acount;
- span->coverage = (unsigned char)coverage;
- if ( ras.num_spans == FT_MAX_GRAY_SPANS )
- {
- /* flush the span buffer and reset the count */
- ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
- ras.num_spans = 0;
- }
- }
- else
- {
- unsigned char* q = ras.target.origin - ras.target.pitch * y + x;
- unsigned char c = (unsigned char)coverage;
+ if ( cover != 0 && cell->x > x )
+ {
+ FT_FILL_RULE( coverage, cover, fill );
+ FT_GRAY_SET( line + x, coverage, cell->x - x );
+ }
+
+ cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+ area = cover - cell->area;
+ if ( area != 0 && cell->x >= ras.min_ex )
+ {
+ FT_FILL_RULE( coverage, area, fill );
+ line[cell->x] = (unsigned char)coverage;
+ }
+
+ x = cell->x + 1;
+ }
- /* For small-spans it is faster to do it by ourselves than
- * calling `memset'. This is mainly due to the cost of the
- * function call.
- */
- switch ( acount )
+ if ( cover != 0 ) /* only if cropped */
{
- case 7:
- *q++ = c;
- /* fall through */
- case 6:
- *q++ = c;
- /* fall through */
- case 5:
- *q++ = c;
- /* fall through */
- case 4:
- *q++ = c;
- /* fall through */
- case 3:
- *q++ = c;
- /* fall through */
- case 2:
- *q++ = c;
- /* fall through */
- case 1:
- *q = c;
- /* fall through */
- case 0:
- break;
- default:
- FT_MEM_SET( q, c, acount );
+ FT_FILL_RULE( coverage, cover, fill );
+ FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
}
}
}
static void
- gray_sweep( RAS_ARG )
+ gray_sweep_direct( RAS_ARG )
{
+ int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+ : INT_MIN;
+ int coverage;
int y;
+ FT_Span span[FT_MAX_GRAY_SPANS];
+ int n = 0;
+
for ( y = ras.min_ey; y < ras.max_ey; y++ )
{
PCell cell = ras.ycells[y - ras.min_ey];
TCoord x = ras.min_ex;
TArea cover = 0;
- TArea area;
- for ( ; cell != NULL; cell = cell->next )
+ for ( ; cell != ras.cell_null; cell = cell->next )
{
+ TArea area;
+
+
if ( cover != 0 && cell->x > x )
- gray_hline( RAS_VAR_ x, y, cover, cell->x - x );
+ {
+ FT_FILL_RULE( coverage, cover, fill );
+
+ span[n].coverage = (unsigned char)coverage;
+ span[n].x = (short)x;
+ span[n].len = (unsigned short)( cell->x - x );
+
+ if ( ++n == FT_MAX_GRAY_SPANS )
+ {
+ /* flush the span buffer and reset the count */
+ ras.render_span( y, n, span, ras.render_span_data );
+ n = 0;
+ }
+ }
cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
area = cover - cell->area;
if ( area != 0 && cell->x >= ras.min_ex )
- gray_hline( RAS_VAR_ cell->x, y, area, 1 );
+ {
+ FT_FILL_RULE( coverage, area, fill );
+
+ span[n].coverage = (unsigned char)coverage;
+ span[n].x = (short)cell->x;
+ span[n].len = 1;
+
+ if ( ++n == FT_MAX_GRAY_SPANS )
+ {
+ /* flush the span buffer and reset the count */
+ ras.render_span( y, n, span, ras.render_span_data );
+ n = 0;
+ }
+ }
x = cell->x + 1;
}
- if ( cover != 0 )
- gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
+ if ( cover != 0 ) /* only if cropped */
+ {
+ FT_FILL_RULE( coverage, cover, fill );
+
+ span[n].coverage = (unsigned char)coverage;
+ span[n].x = (short)x;
+ span[n].len = (unsigned short)( ras.max_ex - x );
+
+ ++n;
+ }
- if ( ras.num_spans > 0 ) /* for FT_RASTER_FLAG_DIRECT only */
+ if ( n )
{
/* flush the span buffer and reset the count */
- ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
- ras.num_spans = 0;
+ ras.render_span( y, n, span, ras.render_span_data );
+ n = 0;
}
}
}
@@ -1389,6 +1678,8 @@ typedef ptrdiff_t FT_PtrDist;
int n; /* index of contour in outline */
int first; /* index of first point in contour */
+ int last; /* index of last point in contour */
+
char tag; /* current point's state */
int shift;
@@ -1403,18 +1694,17 @@ typedef ptrdiff_t FT_PtrDist;
shift = func_interface->shift;
delta = func_interface->delta;
- first = 0;
+ last = -1;
for ( n = 0; n < outline->n_contours; n++ )
{
- int last; /* index of last point in contour */
-
-
- FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
+ FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n ));
+ first = last + 1;
last = outline->contours[n];
- if ( last < 0 )
+ if ( last < first )
goto Invalid_Outline;
+
limit = outline->points + last;
v_start = outline->points[first];
@@ -1597,15 +1887,13 @@ typedef ptrdiff_t FT_PtrDist;
v_start.x / 64.0, v_start.y / 64.0 ));
error = func_interface->line_to( &v_start, user );
- Close:
+ Close:
if ( error )
goto Exit;
-
- first = last + 1;
}
FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
- return 0;
+ return Smooth_Err_Ok;
Exit:
FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
@@ -1632,10 +1920,10 @@ typedef ptrdiff_t FT_PtrDist;
static int
- gray_convert_glyph_inner( RAS_ARG,
+ gray_convert_glyph_inner( RAS_ARG_
int continued )
{
- int error;
+ volatile int error;
if ( ft_setjmp( ras.jump_buffer ) == 0 )
@@ -1646,18 +1934,15 @@ typedef ptrdiff_t FT_PtrDist;
if ( continued )
FT_Trace_Enable();
- if ( !ras.invalid )
- gray_record_cell( RAS_VAR );
-
- FT_TRACE7(( "band [%d..%d]: %d cell%s\n",
+ FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
ras.min_ey,
ras.max_ey,
- ras.num_cells,
- ras.num_cells == 1 ? "" : "s" ));
+ ras.cell_null - ras.cell_free,
+ ras.cell_null - ras.cell_free == 1 ? "" : "s" ));
}
else
{
- error = FT_THROW( Memory_Overflow );
+ error = FT_THROW( Raster_Overflow );
FT_TRACE7(( "band [%d..%d]: to be bisected\n",
ras.min_ey, ras.max_ey ));
@@ -1683,7 +1968,16 @@ typedef ptrdiff_t FT_PtrDist;
int continued = 0;
+ /* 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 */
@@ -1691,13 +1985,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.ycells = (PCell*)buffer;
-
for ( y = yMin; y < yMax; )
{
ras.min_ey = y;
@@ -1711,27 +1998,37 @@ typedef ptrdiff_t FT_PtrDist;
do
{
TCoord width = band[0] - band[1];
+ TCoord w;
int error;
- FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
+ for ( w = 0; w < width; ++w )
+ ras.ycells[w] = ras.cell_null;
+
+ /* memory management: skip ycells */
+ n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+ sizeof ( TCell );
- ras.num_cells = 0;
- ras.invalid = 1;
+ ras.cell_free = buffer + n;
+ ras.cell = ras.cell_null;
ras.min_ey = band[1];
ras.max_ey = band[0];
+ ras.count_ey = width;
- error = gray_convert_glyph_inner( RAS_VAR, continued );
+ error = gray_convert_glyph_inner( RAS_VAR_ continued );
continued = 1;
if ( !error )
{
- gray_sweep( RAS_VAR );
+ if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */
+ gray_sweep_direct( RAS_VAR );
+ else
+ gray_sweep( RAS_VAR );
band--;
continue;
}
- else if ( error != ErrRaster_Memory_Overflow )
- return 1;
+ else if ( error != Smooth_Err_Raster_Overflow )
+ return error;
/* render pool overflow; we will reduce the render band by half */
width >>= 1;
@@ -1740,7 +2037,7 @@ typedef ptrdiff_t FT_PtrDist;
if ( width == 0 )
{
FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
- return 1;
+ return FT_THROW( Raster_Overflow );
}
band++;
@@ -1749,7 +2046,7 @@ typedef ptrdiff_t FT_PtrDist;
} while ( band >= bands );
}
- return 0;
+ return Smooth_Err_Ok;
}
@@ -1770,14 +2067,14 @@ typedef ptrdiff_t FT_PtrDist;
/* this version does not support monochrome rendering */
if ( !( params->flags & FT_RASTER_FLAG_AA ) )
- return FT_THROW( Invalid_Mode );
+ return FT_THROW( Cannot_Render_Glyph );
if ( !outline )
return FT_THROW( Invalid_Outline );
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
- return 0;
+ return Smooth_Err_Ok;
if ( !outline->contours || !outline->points )
return FT_THROW( Invalid_Outline );
@@ -1791,11 +2088,10 @@ typedef ptrdiff_t FT_PtrDist;
if ( params->flags & FT_RASTER_FLAG_DIRECT )
{
if ( !params->gray_spans )
- return 0;
+ return Smooth_Err_Ok;
ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
ras.render_span_data = params->user;
- ras.num_spans = 0;
ras.min_ex = params->clip_box.xMin;
ras.min_ey = params->clip_box.yMin;
@@ -1810,7 +2106,7 @@ typedef ptrdiff_t FT_PtrDist;
/* nothing to do */
if ( !target_map->width || !target_map->rows )
- return 0;
+ return Smooth_Err_Ok;
if ( !target_map->buffer )
return FT_THROW( Invalid_Argument );
@@ -1825,7 +2121,6 @@ typedef ptrdiff_t FT_PtrDist;
ras.render_span = (FT_Raster_Span_Func)NULL;
ras.render_span_data = NULL;
- ras.num_spans = -1; /* invalid */
ras.min_ex = 0;
ras.min_ey = 0;
@@ -1835,7 +2130,7 @@ typedef ptrdiff_t FT_PtrDist;
/* exit if nothing to do */
if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
- return 0;
+ return Smooth_Err_Ok;
return gray_convert_glyph( RAS_VAR );
}
@@ -1872,19 +2167,20 @@ typedef ptrdiff_t FT_PtrDist;
#else /* !STANDALONE_ */
static int
- gray_raster_new( FT_Memory memory,
- FT_Raster* araster )
+ gray_raster_new( void* memory_,
+ FT_Raster* araster_ )
{
+ FT_Memory memory = (FT_Memory)memory_;
+ gray_PRaster* araster = (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;
}
diff --git a/src/3rdparty/freetype/src/smooth/ftgrays.h b/src/3rdparty/freetype/src/smooth/ftgrays.h
index e9f9c7a4ad..a5001bf40d 100644
--- a/src/3rdparty/freetype/src/smooth/ftgrays.h
+++ b/src/3rdparty/freetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
*
* FreeType smooth renderer declaration
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -28,7 +28,7 @@
#include "ftimage.h"
#else
#include <ft2build.h>
-#include FT_IMAGE_H
+#include <freetype/ftimage.h>
#endif
diff --git a/src/3rdparty/freetype/src/smooth/ftsmerrs.h b/src/3rdparty/freetype/src/smooth/ftsmerrs.h
index d52c0dd9e2..f4ac93dc41 100644
--- a/src/3rdparty/freetype/src/smooth/ftsmerrs.h
+++ b/src/3rdparty/freetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
*
* smooth renderer error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -26,7 +26,7 @@
#ifndef FTSMERRS_H_
#define FTSMERRS_H_
-#include FT_MODULE_ERRORS_H
+#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
@@ -34,7 +34,7 @@
#define FT_ERR_PREFIX Smooth_Err_
#define FT_ERR_BASE FT_Mod_Err_Smooth
-#include FT_ERRORS_H
+#include <freetype/fterrors.h>
#endif /* FTSMERRS_H_ */
diff --git a/src/3rdparty/freetype/src/smooth/ftsmooth.c b/src/3rdparty/freetype/src/smooth/ftsmooth.c
index cd034d2b40..9b0e8886cb 100644
--- a/src/3rdparty/freetype/src/smooth/ftsmooth.c
+++ b/src/3rdparty/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -16,46 +16,15 @@
*/
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_OUTLINE_H
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
#include "ftsmooth.h"
#include "ftgrays.h"
#include "ftsmerrs.h"
- /* initialize renderer -- init its raster */
- static FT_Error
- ft_smooth_init( FT_Renderer render )
- {
-
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
- FT_Vector* sub = render->root.library->lcd_geometry;
-
-
- /* set up default subpixel geometry for striped RGB panels. */
- sub[0].x = -21;
- sub[0].y = 0;
- sub[1].x = 0;
- sub[1].y = 0;
- sub[2].x = 21;
- sub[2].y = 0;
-
-#elif 0 /* or else, once ClearType patents expire */
-
- FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT );
-
-#endif
-
- render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
-
- return 0;
- }
-
-
/* sets render-specific mode */
static FT_Error
ft_smooth_set_mode( FT_Renderer render,
@@ -107,14 +76,369 @@
FT_Outline_Get_CBox( &slot->outline, cbox );
}
+ typedef struct TOrigin_
+ {
+ unsigned char* origin; /* pixmap origin at the bottom-left */
+ int pitch; /* pitch to go down one row */
+
+ } TOrigin;
+
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ /* initialize renderer -- init its raster */
+ static FT_Error
+ ft_smooth_init( FT_Module module ) /* FT_Renderer */
+ {
+ FT_Renderer render = (FT_Renderer)module;
+
+ FT_Vector* sub = render->root.library->lcd_geometry;
+
+
+ /* set up default subpixel geometry for striped RGB panels. */
+ sub[0].x = -21;
+ sub[0].y = 0;
+ sub[1].x = 0;
+ sub[1].y = 0;
+ sub[2].x = 21;
+ sub[2].y = 0;
+
+ render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
+
+ return 0;
+ }
+
+
+ /* This function writes every third byte in direct rendering mode */
+ static void
+ ft_smooth_lcd_spans( int y,
+ int count,
+ const FT_Span* spans,
+ void* target_ ) /* TOrigin* */
+ {
+ TOrigin* target = (TOrigin*)target_;
+
+ unsigned char* dst_line = target->origin - y * target->pitch;
+ unsigned char* dst;
+ unsigned short w;
+
+
+ for ( ; count--; spans++ )
+ for ( dst = dst_line + spans->x * 3, w = spans->len; w--; dst += 3 )
+ *dst = spans->coverage;
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_lcd( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Vector* sub = render->root.library->lcd_geometry;
+ FT_Pos x, y;
+
+ FT_Raster_Params params;
+ TOrigin target;
+
+
+ /* Render 3 separate coverage bitmaps, shifting the outline. */
+ /* Set up direct rendering to record them on each third byte. */
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
+ params.gray_spans = ft_smooth_lcd_spans;
+ params.user = &target;
+
+ params.clip_box.xMin = 0;
+ params.clip_box.yMin = 0;
+ params.clip_box.xMax = bitmap->width;
+ params.clip_box.yMax = bitmap->rows;
+
+ if ( bitmap->pitch < 0 )
+ target.origin = bitmap->buffer;
+ else
+ target.origin = bitmap->buffer
+ + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
+
+ target.pitch = bitmap->pitch;
+
+ FT_Outline_Translate( outline,
+ -sub[0].x,
+ -sub[0].y );
+ error = render->raster_render( render->raster, &params );
+ x = sub[0].x;
+ y = sub[0].y;
+ if ( error )
+ goto Exit;
+
+ target.origin++;
+ FT_Outline_Translate( outline,
+ sub[0].x - sub[1].x,
+ sub[0].y - sub[1].y );
+ error = render->raster_render( render->raster, &params );
+ x = sub[1].x;
+ y = sub[1].y;
+ if ( error )
+ goto Exit;
+
+ target.origin++;
+ FT_Outline_Translate( outline,
+ sub[1].x - sub[2].x,
+ sub[1].y - sub[2].y );
+ error = render->raster_render( render->raster, &params );
+ x = sub[2].x;
+ y = sub[2].y;
+
+ Exit:
+ FT_Outline_Translate( outline, x, y );
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_lcdv( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ int pitch = bitmap->pitch;
+ FT_Vector* sub = render->root.library->lcd_geometry;
+ FT_Pos x, y;
+
+ FT_Raster_Params params;
+
+
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
+
+ /* Render 3 separate coverage bitmaps, shifting the outline. */
+ /* Notice that the subpixel geometry vectors are rotated. */
+ /* Triple the pitch to render on each third row. */
+ bitmap->pitch *= 3;
+ bitmap->rows /= 3;
+
+ FT_Outline_Translate( outline,
+ -sub[0].y,
+ sub[0].x );
+ error = render->raster_render( render->raster, &params );
+ x = sub[0].y;
+ y = -sub[0].x;
+ if ( error )
+ goto Exit;
+
+ bitmap->buffer += pitch;
+ FT_Outline_Translate( outline,
+ sub[0].y - sub[1].y,
+ sub[1].x - sub[0].x );
+ error = render->raster_render( render->raster, &params );
+ x = sub[1].y;
+ y = -sub[1].x;
+ bitmap->buffer -= pitch;
+ if ( error )
+ goto Exit;
+
+ bitmap->buffer += 2 * pitch;
+ FT_Outline_Translate( outline,
+ sub[1].y - sub[2].y,
+ sub[2].x - sub[1].x );
+ error = render->raster_render( render->raster, &params );
+ x = sub[2].y;
+ y = -sub[2].x;
+ bitmap->buffer -= 2 * pitch;
+
+ Exit:
+ FT_Outline_Translate( outline, x, y );
+
+ bitmap->pitch /= 3;
+ bitmap->rows *= 3;
+
+ return error;
+ }
+
+#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+ /* initialize renderer -- init its raster */
+ static FT_Error
+ ft_smooth_init( FT_Module module ) /* FT_Renderer */
+ {
+ FT_Renderer render = (FT_Renderer)module;
+
+
+ /* set up default LCD filtering */
+ FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT );
+
+ render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
+
+ return 0;
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_lcd( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
+ FT_Vector* vec;
+
+ FT_Raster_Params params;
+
+
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
+
+ /* implode outline */
+ for ( vec = points; vec < points_end; vec++ )
+ vec->x *= 3;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* deflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ vec->x /= 3;
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_lcdv( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
+ FT_Vector* vec;
+
+ FT_Raster_Params params;
+
+
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
+
+ /* implode outline */
+ for ( vec = points; vec < points_end; vec++ )
+ vec->y *= 3;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* deflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ vec->y /= 3;
+
+ return error;
+ }
+
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+/* Oversampling scale to be used in rendering overlaps */
+#define SCALE ( 1 << 2 )
+
+ /* This function averages inflated spans in direct rendering mode */
+ static void
+ ft_smooth_overlap_spans( int y,
+ int count,
+ const FT_Span* spans,
+ void* target_ )
+ {
+ TOrigin* target = (TOrigin*)target_;
+
+
+ unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch;
+ unsigned short x;
+ unsigned int cover, sum;
+
+
+ /* When accumulating the oversampled spans we need to assure that */
+ /* fully covered pixels are equal to 255 and do not overflow. */
+ /* It is important that the SCALE is a power of 2, each subpixel */
+ /* cover can also reach a power of 2 after rounding, and the total */
+ /* is clamped to 255 when it adds up to 256. */
+ for ( ; count--; spans++ )
+ {
+ cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE );
+ for ( x = 0; x < spans->len; x++ )
+ {
+ sum = dst[( spans->x + x ) / SCALE] + cover;
+ dst[( spans->x + x ) / SCALE] = (unsigned char)( sum - ( sum >> 8 ) );
+ }
+ }
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_overlap( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
+ FT_Vector* vec;
+
+ FT_Raster_Params params;
+ TOrigin target;
+
+
+ /* Reject outlines that are too wide for 16-bit FT_Span. */
+ /* Other limits are applied upstream with the same error code. */
+ if ( bitmap->width * SCALE > 0x7FFF )
+ return FT_THROW( Raster_Overflow );
+
+ /* Set up direct rendering to average oversampled spans. */
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
+ params.gray_spans = ft_smooth_overlap_spans;
+ params.user = &target;
+
+ params.clip_box.xMin = 0;
+ params.clip_box.yMin = 0;
+ params.clip_box.xMax = bitmap->width * SCALE;
+ params.clip_box.yMax = bitmap->rows * SCALE;
+
+ if ( bitmap->pitch < 0 )
+ target.origin = bitmap->buffer;
+ else
+ target.origin = bitmap->buffer
+ + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
+
+ target.pitch = bitmap->pitch;
+
+ /* inflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ {
+ vec->x *= SCALE;
+ vec->y *= SCALE;
+ }
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* deflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ {
+ vec->x /= SCALE;
+ vec->y /= SCALE;
+ }
+
+ return error;
+ }
+
+#undef SCALE
- /* convert a slot's glyph image into a bitmap */
static FT_Error
- ft_smooth_render_generic( FT_Renderer render,
- FT_GlyphSlot slot,
- FT_Render_Mode mode,
- const FT_Vector* origin,
- FT_Render_Mode required_mode )
+ ft_smooth_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
{
FT_Error error = FT_Err_Ok;
FT_Outline* outline = &slot->outline;
@@ -122,10 +446,6 @@
FT_Memory memory = render->root.memory;
FT_Pos x_shift = 0;
FT_Pos y_shift = 0;
- FT_Int hmul = ( mode == FT_RENDER_MODE_LCD );
- FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V );
-
- FT_Raster_Params params;
/* check glyph image format */
@@ -136,7 +456,10 @@
}
/* check mode */
- if ( mode != required_mode )
+ if ( mode != FT_RENDER_MODE_NORMAL &&
+ mode != FT_RENDER_MODE_LIGHT &&
+ mode != FT_RENDER_MODE_LCD &&
+ mode != FT_RENDER_MODE_LCD_V )
{
error = FT_THROW( Cannot_Render_Glyph );
goto Exit;
@@ -155,6 +478,9 @@
goto Exit;
}
+ if ( !bitmap->rows || !bitmap->pitch )
+ goto Exit;
+
/* allocate new one */
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
goto Exit;
@@ -178,188 +504,57 @@
if ( x_shift || y_shift )
FT_Outline_Translate( outline, x_shift, y_shift );
- /* set up parameters */
- params.target = bitmap;
- params.source = outline;
- params.flags = FT_RASTER_FLAG_AA;
-
-#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
- /* implode outline if needed */
+ if ( mode == FT_RENDER_MODE_NORMAL ||
+ mode == FT_RENDER_MODE_LIGHT )
{
- FT_Vector* points = outline->points;
- FT_Vector* points_end = points + outline->n_points;
- FT_Vector* vec;
-
-
- if ( hmul )
- for ( vec = points; vec < points_end; vec++ )
- vec->x *= 3;
-
- if ( vmul )
- for ( vec = points; vec < points_end; vec++ )
- vec->y *= 3;
- }
-
- /* render outline into the bitmap */
- error = render->raster_render( render->raster, &params );
-
- /* deflate outline if needed */
- {
- FT_Vector* points = outline->points;
- FT_Vector* points_end = points + outline->n_points;
- FT_Vector* vec;
+ if ( outline->flags & FT_OUTLINE_OVERLAP )
+ error = ft_smooth_raster_overlap( render, outline, bitmap );
+ else
+ {
+ FT_Raster_Params params;
- if ( hmul )
- for ( vec = points; vec < points_end; vec++ )
- vec->x /= 3;
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
- if ( vmul )
- for ( vec = points; vec < points_end; vec++ )
- vec->y /= 3;
+ error = render->raster_render( render->raster, &params );
+ }
}
-
- if ( error )
- goto Exit;
-
- /* finally apply filtering */
- if ( hmul || vmul )
+ else
{
- FT_Byte* lcd_weights;
- FT_Bitmap_LcdFilterFunc lcd_filter_func;
+ if ( mode == FT_RENDER_MODE_LCD )
+ error = ft_smooth_raster_lcd ( render, outline, bitmap );
+ else if ( mode == FT_RENDER_MODE_LCD_V )
+ error = ft_smooth_raster_lcdv( render, outline, bitmap );
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- /* Per-face LCD filtering takes priority if set up. */
- if ( slot->face && slot->face->internal->lcd_filter_func )
- {
- lcd_weights = slot->face->internal->lcd_weights;
- lcd_filter_func = slot->face->internal->lcd_filter_func;
- }
- else
+ /* finally apply filtering */
{
- lcd_weights = slot->library->lcd_weights;
- lcd_filter_func = slot->library->lcd_filter_func;
- }
-
- if ( lcd_filter_func )
- lcd_filter_func( bitmap, lcd_weights );
- }
+ FT_Byte* lcd_weights;
+ FT_Bitmap_LcdFilterFunc lcd_filter_func;
-#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- if ( hmul ) /* lcd */
- {
- FT_Byte* line;
- FT_Byte* temp = NULL;
- FT_UInt i, j;
-
- unsigned int height = bitmap->rows;
- unsigned int width = bitmap->width;
- int pitch = bitmap->pitch;
-
- FT_Vector* sub = slot->library->lcd_geometry;
-
-
- /* Render 3 separate monochrome bitmaps, shifting the outline. */
- width /= 3;
-
- FT_Outline_Translate( outline,
- -sub[0].x,
- -sub[0].y );
- error = render->raster_render( render->raster, &params );
- if ( error )
- goto Exit;
-
- bitmap->buffer += width;
- FT_Outline_Translate( outline,
- sub[0].x - sub[1].x,
- sub[0].y - sub[1].y );
- error = render->raster_render( render->raster, &params );
- bitmap->buffer -= width;
- if ( error )
- goto Exit;
-
- bitmap->buffer += 2 * width;
- FT_Outline_Translate( outline,
- sub[1].x - sub[2].x,
- sub[1].y - sub[2].y );
- error = render->raster_render( render->raster, &params );
- bitmap->buffer -= 2 * width;
- if ( error )
- goto Exit;
-
- x_shift -= sub[2].x;
- y_shift -= sub[2].y;
-
- /* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
- /* XXX: It is more efficient to render every third byte above. */
-
- if ( FT_ALLOC( temp, (FT_ULong)pitch ) )
- goto Exit;
-
- for ( i = 0; i < height; i++ )
- {
- line = bitmap->buffer + i * (FT_ULong)pitch;
- for ( j = 0; j < width; j++ )
+ /* Per-face LCD filtering takes priority if set up. */
+ if ( slot->face && slot->face->internal->lcd_filter_func )
{
- temp[3 * j ] = line[j];
- temp[3 * j + 1] = line[j + width];
- temp[3 * j + 2] = line[j + width + width];
+ lcd_weights = slot->face->internal->lcd_weights;
+ lcd_filter_func = slot->face->internal->lcd_filter_func;
}
- FT_MEM_COPY( line, temp, pitch );
+ else
+ {
+ lcd_weights = slot->library->lcd_weights;
+ lcd_filter_func = slot->library->lcd_filter_func;
+ }
+
+ if ( lcd_filter_func )
+ lcd_filter_func( bitmap, lcd_weights );
}
- FT_FREE( temp );
- }
- else if ( vmul ) /* lcd_v */
- {
- int pitch = bitmap->pitch;
-
- FT_Vector* sub = slot->library->lcd_geometry;
-
-
- /* Render 3 separate monochrome bitmaps, shifting the outline. */
- /* Notice that the subpixel geometry vectors are rotated. */
- /* Triple the pitch to render on each third row. */
- bitmap->pitch *= 3;
- bitmap->rows /= 3;
-
- FT_Outline_Translate( outline,
- -sub[0].y,
- sub[0].x );
- error = render->raster_render( render->raster, &params );
- if ( error )
- goto Exit;
-
- bitmap->buffer += pitch;
- FT_Outline_Translate( outline,
- sub[0].y - sub[1].y,
- sub[1].x - sub[0].x );
- error = render->raster_render( render->raster, &params );
- bitmap->buffer -= pitch;
- if ( error )
- goto Exit;
-
- bitmap->buffer += 2 * pitch;
- FT_Outline_Translate( outline,
- sub[1].y - sub[2].y,
- sub[2].x - sub[1].x );
- error = render->raster_render( render->raster, &params );
- bitmap->buffer -= 2 * pitch;
- if ( error )
- goto Exit;
-
- x_shift -= sub[2].y;
- y_shift += sub[2].x;
-
- bitmap->pitch /= 3;
- bitmap->rows *= 3;
- }
- else /* grayscale */
- error = render->raster_render( render->raster, &params );
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
-#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+ }
Exit:
if ( !error )
@@ -380,45 +575,6 @@
}
- /* convert a slot's glyph image into a bitmap */
- static FT_Error
- ft_smooth_render( FT_Renderer render,
- FT_GlyphSlot slot,
- FT_Render_Mode mode,
- const FT_Vector* origin )
- {
- if ( mode == FT_RENDER_MODE_LIGHT )
- mode = FT_RENDER_MODE_NORMAL;
-
- return ft_smooth_render_generic( render, slot, mode, origin,
- FT_RENDER_MODE_NORMAL );
- }
-
-
- /* convert a slot's glyph image into a horizontal LCD bitmap */
- static FT_Error
- ft_smooth_render_lcd( FT_Renderer render,
- FT_GlyphSlot slot,
- FT_Render_Mode mode,
- const FT_Vector* origin )
- {
- return ft_smooth_render_generic( render, slot, mode, origin,
- FT_RENDER_MODE_LCD );
- }
-
-
- /* convert a slot's glyph image into a vertical LCD bitmap */
- static FT_Error
- ft_smooth_render_lcd_v( FT_Renderer render,
- FT_GlyphSlot slot,
- FT_Render_Mode mode,
- const FT_Vector* origin )
- {
- return ft_smooth_render_generic( render, slot, mode, origin,
- FT_RENDER_MODE_LCD_V );
- }
-
-
FT_DEFINE_RENDERER(
ft_smooth_renderer_class,
@@ -446,58 +602,4 @@
)
- FT_DEFINE_RENDERER(
- ft_smooth_lcd_renderer_class,
-
- FT_MODULE_RENDERER,
- sizeof ( FT_RendererRec ),
-
- "smooth-lcd",
- 0x10000L,
- 0x20000L,
-
- NULL, /* module specific interface */
-
- (FT_Module_Constructor)ft_smooth_init, /* module_init */
- (FT_Module_Destructor) NULL, /* module_done */
- (FT_Module_Requester) NULL, /* get_interface */
-
- FT_GLYPH_FORMAT_OUTLINE,
-
- (FT_Renderer_RenderFunc) ft_smooth_render_lcd, /* render_glyph */
- (FT_Renderer_TransformFunc)ft_smooth_transform, /* transform_glyph */
- (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */
- (FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */
-
- (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */
- )
-
-
- FT_DEFINE_RENDERER(
- ft_smooth_lcdv_renderer_class,
-
- FT_MODULE_RENDERER,
- sizeof ( FT_RendererRec ),
-
- "smooth-lcdv",
- 0x10000L,
- 0x20000L,
-
- NULL, /* module specific interface */
-
- (FT_Module_Constructor)ft_smooth_init, /* module_init */
- (FT_Module_Destructor) NULL, /* module_done */
- (FT_Module_Requester) NULL, /* get_interface */
-
- FT_GLYPH_FORMAT_OUTLINE,
-
- (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v, /* render_glyph */
- (FT_Renderer_TransformFunc)ft_smooth_transform, /* transform_glyph */
- (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */
- (FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */
-
- (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */
- )
-
-
/* END */
diff --git a/src/3rdparty/freetype/src/smooth/ftsmooth.h b/src/3rdparty/freetype/src/smooth/ftsmooth.h
index fbb21a31d0..f8bdc9938b 100644
--- a/src/3rdparty/freetype/src/smooth/ftsmooth.h
+++ b/src/3rdparty/freetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -20,8 +20,7 @@
#define FTSMOOTH_H_
-#include <ft2build.h>
-#include FT_RENDER_H
+#include <freetype/ftrender.h>
FT_BEGIN_HEADER
@@ -29,10 +28,6 @@ FT_BEGIN_HEADER
FT_DECLARE_RENDERER( ft_smooth_renderer_class )
- FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class )
-
- FT_DECLARE_RENDERER( ft_smooth_lcdv_renderer_class )
-
FT_END_HEADER
diff --git a/src/3rdparty/freetype/src/smooth/ftspic.c b/src/3rdparty/freetype/src/smooth/ftspic.c
deleted file mode 100644
index 10f04cf4cc..0000000000
--- a/src/3rdparty/freetype/src/smooth/ftspic.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftspic.c */
-/* */
-/* The FreeType position independent code services for smooth module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "ftspic.h"
-#include "ftsmerrs.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ftgrays.c */
- void
- FT_Init_Class_ft_grays_raster( FT_Raster_Funcs* funcs );
-
-
- void
- ft_smooth_renderer_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->smooth )
- {
- SmoothPIC* container = (SmoothPIC*)pic_container->smooth;
-
-
- if ( --container->ref_count )
- return;
-
- FT_FREE( container );
- pic_container->smooth = NULL;
- }
- }
-
-
- FT_Error
- ft_smooth_renderer_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- SmoothPIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* since this function also serve smooth_lcd and smooth_lcdv renderers,
- it implements reference counting */
- if ( pic_container->smooth )
- {
- ((SmoothPIC*)pic_container->smooth)->ref_count++;
- return error;
- }
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->smooth = container;
-
- container->ref_count = 1;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- FT_Init_Class_ft_grays_raster( &container->ft_grays_raster );
-
- return error;
- }
-
-
- /* re-route these init and free functions to the above functions */
- FT_Error
- ft_smooth_lcd_renderer_class_pic_init( FT_Library library )
- {
- return ft_smooth_renderer_class_pic_init( library );
- }
-
-
- void
- ft_smooth_lcd_renderer_class_pic_free( FT_Library library )
- {
- ft_smooth_renderer_class_pic_free( library );
- }
-
-
- FT_Error
- ft_smooth_lcdv_renderer_class_pic_init( FT_Library library )
- {
- return ft_smooth_renderer_class_pic_init( library );
- }
-
-
- void
- ft_smooth_lcdv_renderer_class_pic_free( FT_Library library )
- {
- ft_smooth_renderer_class_pic_free( library );
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/src/3rdparty/freetype/src/smooth/ftspic.h b/src/3rdparty/freetype/src/smooth/ftspic.h
deleted file mode 100644
index 80fb64cff4..0000000000
--- a/src/3rdparty/freetype/src/smooth/ftspic.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftspic.h */
-/* */
-/* The FreeType position independent code services for smooth module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTSPIC_H_
-#define FTSPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-FT_BEGIN_HEADER
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_GRAYS_RASTER_GET ft_grays_raster
-
-#else /* FT_CONFIG_OPTION_PIC */
-
- typedef struct SmoothPIC_
- {
- int ref_count;
- FT_Raster_Funcs ft_grays_raster;
-
- } SmoothPIC;
-
-
-#define GET_PIC( lib ) \
- ( (SmoothPIC*)( (lib)->pic_container.smooth ) )
-#define FT_GRAYS_RASTER_GET ( GET_PIC( library )->ft_grays_raster )
-
-
- /* see ftspic.c for the implementation */
- void
- ft_smooth_renderer_class_pic_free( FT_Library library );
-
- void
- ft_smooth_lcd_renderer_class_pic_free( FT_Library library );
-
- void
- ft_smooth_lcdv_renderer_class_pic_free( FT_Library library );
-
- FT_Error
- ft_smooth_renderer_class_pic_init( FT_Library library );
-
- FT_Error
- ft_smooth_lcd_renderer_class_pic_init( FT_Library library );
-
- FT_Error
- ft_smooth_lcdv_renderer_class_pic_init( FT_Library library );
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-FT_END_HEADER
-
-#endif /* FTSPIC_H_ */
-
-
-/* END */
diff --git a/src/3rdparty/freetype/src/smooth/module.mk b/src/3rdparty/freetype/src/smooth/module.mk
index 44b76dfec6..82ab2fa596 100644
--- a/src/3rdparty/freetype/src/smooth/module.mk
+++ b/src/3rdparty/freetype/src/smooth/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2023 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -18,10 +18,6 @@ FTMODULE_H_COMMANDS += SMOOTH_RENDERER
define SMOOTH_RENDERER
$(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_renderer_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer$(ECHO_DRIVER_DONE)
-$(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_lcd_renderer_class $(CLOSE_DRIVER)
-$(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer for LCDs$(ECHO_DRIVER_DONE)
-$(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_lcdv_renderer_class $(CLOSE_DRIVER)
-$(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer for vertical LCDs$(ECHO_DRIVER_DONE)
endef
# EOF
diff --git a/src/3rdparty/freetype/src/smooth/rules.mk b/src/3rdparty/freetype/src/smooth/rules.mk
index 0153ac24a4..5d89c75407 100644
--- a/src/3rdparty/freetype/src/smooth/rules.mk
+++ b/src/3rdparty/freetype/src/smooth/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2023 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/3rdparty/freetype/src/smooth/smooth.c b/src/3rdparty/freetype/src/smooth/smooth.c
index 9c543d3360..9a0b824c2a 100644
--- a/src/3rdparty/freetype/src/smooth/smooth.c
+++ b/src/3rdparty/freetype/src/smooth/smooth.c
@@ -4,7 +4,7 @@
*
* FreeType anti-aliasing rasterer module component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -17,7 +17,6 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
-#include <ft2build.h>
#include "ftgrays.c"
#include "ftsmooth.c"