Compare commits
22 Commits
master
...
gsoc-anura
Author | SHA1 | Date | |
---|---|---|---|
|
b1f9f98e45 | ||
|
c1804c48a9 | ||
|
2254ce1906 | ||
|
b2f570a2bb | ||
|
e7c4fb9d13 | ||
|
d074c39cd9 | ||
|
c33e0b82de | ||
|
45de1dba73 | ||
|
3b3c46629e | ||
|
1bf65eff60 | ||
|
cf779f5fbf | ||
|
724e81ef5b | ||
|
668bc29ff0 | ||
|
bca7bda1e7 | ||
|
3e56c9bf62 | ||
|
70d6a8ef1a | ||
|
2504e2de84 | ||
|
5e681678f6 | ||
|
f2ff1dc37e | ||
|
abce0cab72 | ||
|
f681099918 | ||
|
a78906fb4e |
@ -247,6 +247,8 @@ if (BUILD_FRAMEWORK)
|
||||
endif ()
|
||||
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.1")
|
||||
|
||||
# Find dependencies
|
||||
include(FindPkgConfig)
|
||||
|
||||
@ -405,6 +407,7 @@ set(BASE_SRCS
|
||||
src/cache/ftcache.c
|
||||
src/cff/cff.c
|
||||
src/cid/type1cid.c
|
||||
src/dense/dense.c
|
||||
src/gzip/ftgzip.c
|
||||
src/lzw/ftlzw.c
|
||||
src/pcf/pcf.c
|
||||
|
@ -87,6 +87,7 @@ def generate_ftmodule(lists):
|
||||
names = {
|
||||
"raster": ("ft_raster1",),
|
||||
"smooth": ("ft_smooth",),
|
||||
"dense": ("ft_dense",),
|
||||
"svg": ("ft_svg",),
|
||||
"sdf": ("ft_sdf", "ft_bitmap_sdf"),
|
||||
}.get(module)
|
||||
|
@ -24,6 +24,7 @@ FT_USE_MODULE( FT_Module_Class, psaux_module_class )
|
||||
FT_USE_MODULE( FT_Module_Class, psnames_module_class )
|
||||
FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
|
||||
FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
|
||||
FT_USE_MODULE( FT_Renderer_Class, ft_dense_renderer_class )
|
||||
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
|
||||
FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
|
||||
FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
|
||||
|
@ -1276,6 +1276,7 @@ FT_BEGIN_HEADER
|
||||
FT_ListRec sizes_list;
|
||||
|
||||
FT_Generic autohint; /* face-specific auto-hinter data */
|
||||
FT_GlyphSlot* glyph_array;
|
||||
void* extensions; /* unused */
|
||||
|
||||
FT_Face_Internal internal;
|
||||
@ -1283,6 +1284,44 @@ FT_BEGIN_HEADER
|
||||
} FT_FaceRec;
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @type:
|
||||
* FT_PreLine
|
||||
*
|
||||
* @description:
|
||||
* A handle to FT_PreLineRec_ containing coordinates of start and end
|
||||
* points for a line.
|
||||
*
|
||||
*/
|
||||
typedef struct FT_PreLineRec_* FT_PreLine;
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
* FT_PreLineRec
|
||||
*
|
||||
* @description:
|
||||
* Linkedlist containing lines to be drawn for a glyph.
|
||||
*
|
||||
* @fields:
|
||||
* x1, y1 ::
|
||||
* Coordinates of line start point.
|
||||
*
|
||||
* y1, y2 ::
|
||||
* Coordinates of line end point.
|
||||
*
|
||||
* next ::
|
||||
* The next PreLine for current glyph
|
||||
*
|
||||
*/
|
||||
typedef struct FT_PreLineRec_
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
FT_PreLine next;
|
||||
} FT_PreLineRec;
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @enum:
|
||||
@ -2171,6 +2210,12 @@ FT_BEGIN_HEADER
|
||||
* other ::
|
||||
* Reserved.
|
||||
*
|
||||
* prelines ::
|
||||
* Linkedlist containing lines to be drawn for the glyph
|
||||
*
|
||||
* prel_shifted ::
|
||||
* If the points in preline have been adjustted according to target bitmap
|
||||
*
|
||||
* lsb_delta ::
|
||||
* The difference between hinted and unhinted left side bearing while
|
||||
* auto-hinting is active. Zero otherwise.
|
||||
@ -2288,6 +2333,8 @@ FT_BEGIN_HEADER
|
||||
FT_Pos rsb_delta;
|
||||
|
||||
void* other;
|
||||
FT_PreLine prelines;
|
||||
int prel_shifted;
|
||||
|
||||
FT_Slot_Internal internal;
|
||||
|
||||
@ -2487,6 +2534,10 @@ FT_BEGIN_HEADER
|
||||
* params ::
|
||||
* Extra parameters passed to the font driver when opening a new face.
|
||||
*
|
||||
* size ::
|
||||
* Size at which the glyphs will be rendered. Use same value as
|
||||
* @FT_Set_Pixel_Sizes
|
||||
*
|
||||
* @note:
|
||||
* The stream type is determined by the contents of `flags`:
|
||||
*
|
||||
@ -2524,6 +2575,7 @@ FT_BEGIN_HEADER
|
||||
FT_Module driver;
|
||||
FT_Int num_params;
|
||||
FT_Parameter* params;
|
||||
FT_UInt size;
|
||||
|
||||
} FT_Open_Args;
|
||||
|
||||
@ -2573,6 +2625,54 @@ FT_BEGIN_HEADER
|
||||
FT_Face *aface );
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_New_Face2
|
||||
*
|
||||
* @description:
|
||||
* Call @FT_Open_Face to open a font by its pathname with given flags.
|
||||
*
|
||||
* @inout:
|
||||
* library ::
|
||||
* A handle to the library resource.
|
||||
*
|
||||
* @input:
|
||||
* pathname ::
|
||||
* A path to the font file.
|
||||
*
|
||||
* face_index ::
|
||||
* See @FT_Open_Face for a detailed description of this parameter.
|
||||
*
|
||||
* size ::
|
||||
* Size at which glyphs will be rendered, Use the same value as @FT_Set_Pixel_Sizes
|
||||
*
|
||||
* @output:
|
||||
* aface ::
|
||||
* A handle to a new face object. If `face_index` is greater than or
|
||||
* equal to zero, it must be non-`NULL`.
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0~means success.
|
||||
*
|
||||
* @note:
|
||||
* The `pathname` string should be recognizable as such by a standard
|
||||
* `fopen` call on your system; in particular, this means that `pathname`
|
||||
* must not contain null bytes. If that is not sufficient to address all
|
||||
* file name possibilities (for example, to handle wide character file
|
||||
* names on Windows in UTF-16 encoding) you might use @FT_Open_Face to
|
||||
* pass a memory array or a stream object instead.
|
||||
*
|
||||
* Use @FT_Done_Face to destroy the created @FT_Face object (along with
|
||||
* its slot and sizes).
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_New_Face2( FT_Library library,
|
||||
const char* filepathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface,
|
||||
FT_UInt size);
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @function:
|
||||
@ -3228,6 +3328,31 @@ FT_BEGIN_HEADER
|
||||
FT_UInt glyph_index,
|
||||
FT_Int32 load_flags );
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_Refresh_Glyph
|
||||
*
|
||||
* @description:
|
||||
* Prepare the glyph at glyph_index for rendering. Resets the glyph
|
||||
* if it has already been rendered
|
||||
*
|
||||
* @inout:
|
||||
* face ::
|
||||
* A handle to the target face object where the glyph is loaded.
|
||||
*
|
||||
* @input:
|
||||
* glyph_index ::
|
||||
* The index of the glyph in the font file.
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0~means success.
|
||||
*
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Refresh_Glyph( FT_Face face,
|
||||
FT_UInt glyph_index);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
|
@ -1030,6 +1030,9 @@ FT_BEGIN_HEADER
|
||||
* An optional span clipping box expressed in _integer_ pixels
|
||||
* (not in 26.6 fixed-point units).
|
||||
*
|
||||
* prelines ::
|
||||
* Pointer of type FT_PreLine, containing line data for a glyph
|
||||
*
|
||||
* @note:
|
||||
* The @FT_RASTER_FLAG_AA bit flag must be set in the `flags` to
|
||||
* generate an anti-aliased glyph bitmap, otherwise a monochrome bitmap
|
||||
@ -1059,6 +1062,7 @@ FT_BEGIN_HEADER
|
||||
FT_Raster_BitSet_Func bit_set; /* unused */
|
||||
void* user;
|
||||
FT_BBox clip_box;
|
||||
void* prelines;
|
||||
|
||||
} FT_Raster_Params;
|
||||
|
||||
|
@ -395,6 +395,13 @@ if use_unix_ftsystem_c
|
||||
endif
|
||||
|
||||
|
||||
if cc.get_id() == 'msvc'
|
||||
ft2_defines += ['/arch:AVX']
|
||||
else
|
||||
ft2_defines += ['-msse4.1']
|
||||
endif
|
||||
|
||||
|
||||
ft2_lib = library('freetype',
|
||||
sources: ft2_sources + [ftmodule_h],
|
||||
c_args: ft2_defines,
|
||||
@ -403,7 +410,7 @@ ft2_lib = library('freetype',
|
||||
dependencies: ft2_deps,
|
||||
install: true,
|
||||
version: ft2_so_version,
|
||||
link_args: common_ldflags,
|
||||
link_args: common_ldflags + ['-lm'],
|
||||
)
|
||||
|
||||
|
||||
|
@ -93,6 +93,9 @@ HINTING_MODULES += pshinter
|
||||
#### raster modules -- at least one is required for vector font formats
|
||||
####
|
||||
|
||||
# Dense Rasterizer
|
||||
RASTER_MODULES += dense
|
||||
|
||||
# Anti-aliasing rasterizer.
|
||||
RASTER_MODULES += smooth
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <freetype/internal/services/svkern.h>
|
||||
#include <freetype/internal/services/svtteng.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <freetype/ftdriver.h>
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_MAC_FONTS
|
||||
@ -893,6 +894,14 @@
|
||||
|
||||
|
||||
/* documentation is in freetype.h */
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_Refresh_Glyph( FT_Face face,
|
||||
FT_UInt glyph_index)
|
||||
|
||||
{
|
||||
ft_glyphslot_free_bitmap( face->glyph_array[glyph_index] );
|
||||
face->glyph_array[glyph_index]->format = FT_GLYPH_FORMAT_OUTLINE;
|
||||
}
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_Load_Glyph( FT_Face face,
|
||||
@ -914,7 +923,7 @@
|
||||
/* The validity test for `glyph_index' is performed by the */
|
||||
/* font drivers. */
|
||||
|
||||
slot = face->glyph;
|
||||
slot = face->glyph_array[glyph_index];
|
||||
ft_glyphslot_clear( slot );
|
||||
|
||||
driver = face->driver;
|
||||
@ -1616,12 +1625,34 @@
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
args.flags = FT_OPEN_PATHNAME;
|
||||
args.size = 0;
|
||||
args.pathname = (char*)pathname;
|
||||
args.stream = NULL;
|
||||
|
||||
return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
||||
}
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_New_Face2( FT_Library library,
|
||||
const char* pathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface,
|
||||
FT_UInt size)
|
||||
{
|
||||
FT_Open_Args args;
|
||||
|
||||
/* test for valid `library' and `aface' delayed to `FT_Open_Face' */
|
||||
if ( !pathname )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
args.flags = FT_OPEN_PATHNAME;
|
||||
args.size = size;
|
||||
args.pathname = (char*)pathname;
|
||||
args.stream = NULL;
|
||||
|
||||
return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -2519,6 +2550,306 @@
|
||||
}
|
||||
|
||||
|
||||
static FT_Vector
|
||||
Lerp( float T, FT_Vector P0, FT_Vector P1 )
|
||||
{
|
||||
FT_Vector p;
|
||||
p.x = P0.x + T * ( P1.x - P0.x );
|
||||
p.y = P0.y + T * ( P1.y - P0.y );
|
||||
return p;
|
||||
}
|
||||
|
||||
int conic_to2(FT_GlyphSlot* slot, FT_Vector *control, FT_Vector *from, FT_Vector *to, FT_PreLine *ptr)
|
||||
{
|
||||
/*
|
||||
Calculate devsq as the square of four times the
|
||||
distance from the control point to the midpoint of the curve.
|
||||
This is the place at which the curve is furthest from the
|
||||
line joining the control points.
|
||||
|
||||
4 x point on curve = p0 + 2p1 + p2
|
||||
4 x midpoint = 4p1
|
||||
|
||||
The division by four is omitted to save time.
|
||||
*/
|
||||
FT_Vector aP0 = { from->x , from->y};
|
||||
FT_Vector aP1 = { control->x, control->y };
|
||||
FT_Vector aP2 = { to->x, to->y };
|
||||
|
||||
float devx = aP0.x - aP1.x - aP1.x + aP2.x;
|
||||
float devy = aP0.y - aP1.y - aP1.y + aP2.y;
|
||||
float devsq = devx * devx + devy * devy;
|
||||
|
||||
if ( devsq < 0.333f )
|
||||
{
|
||||
FT_PreLine pl3 = malloc(sizeof(FT_PreLineRec));
|
||||
pl3->x1 = (*ptr)->x2;
|
||||
pl3->y1 = (*ptr)->y2;
|
||||
pl3->x2 = aP2.x;
|
||||
pl3->y2 = aP2.y;
|
||||
pl3->next = NULL;
|
||||
(*ptr)->next = pl3;
|
||||
*ptr = (*ptr)->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
According to Raph Levien, the reason for the subdivision by n (instead of
|
||||
recursive division by the Casteljau system) is that "I expect the flatness
|
||||
computation to be semi-expensive (it's done once rather than on each potential
|
||||
subdivision) and also because you'll often get fewer subdivisions. Taking a
|
||||
circular arc as a simplifying assumption, where I get n, a recursive approach
|
||||
would get 2^ceil(lg n), which, if I haven't made any horrible mistakes, is
|
||||
expected to be 33% more in the limit".
|
||||
*/
|
||||
|
||||
const float tol = 3.0f;
|
||||
int n = (int)floor( sqrt( sqrt( tol * devsq ) ) )/8;
|
||||
FT_Vector p = aP0;
|
||||
float nrecip = 1.0f / ( n + 1.0f );
|
||||
float t = 0.0f;
|
||||
for ( int i = 0; i < n; i++ )
|
||||
{
|
||||
t += nrecip;
|
||||
FT_Vector next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
|
||||
FT_PreLine pl4 = malloc(sizeof(FT_PreLineRec));
|
||||
pl4->x1 = (*ptr)->x2;
|
||||
pl4->y1 = (*ptr)->y2;
|
||||
pl4->x2 = next.x;
|
||||
pl4->y2 = next.y;
|
||||
pl4->next = NULL;
|
||||
(*ptr)->next = pl4;
|
||||
*ptr = (*ptr)->next;
|
||||
p = next;
|
||||
}
|
||||
|
||||
FT_PreLine pl5 = malloc(sizeof(FT_PreLineRec));
|
||||
pl5->x1 = (*ptr)->x2;
|
||||
pl5->y1 = (*ptr)->y2;
|
||||
pl5->x2 = aP2.x;
|
||||
pl5->y2 = aP2.y;
|
||||
pl5->next = NULL;
|
||||
(*ptr)->next = pl5;
|
||||
*ptr = (*ptr)->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the outline data of slot to prelines
|
||||
*/
|
||||
FT_Error ft_decompose_outline(FT_GlyphSlot* slot){
|
||||
FT_Vector v_last;
|
||||
FT_Vector v_control;
|
||||
FT_Vector v_start;
|
||||
|
||||
FT_Vector* point;
|
||||
FT_Vector* limit;
|
||||
char* tags;
|
||||
|
||||
FT_Error error;
|
||||
|
||||
FT_Int n; /* index of contour in outline */
|
||||
FT_Int first; /* index of first point in contour */
|
||||
FT_Int last; /* index of last point in contour */
|
||||
|
||||
FT_Int tag; /* current point's state */
|
||||
|
||||
FT_Int shift;
|
||||
FT_Pos delta;
|
||||
|
||||
FT_Outline* outline = &(*slot)->outline;
|
||||
|
||||
if ( !outline )
|
||||
return FT_THROW( Invalid_Outline );
|
||||
|
||||
last = -1;
|
||||
FT_PreLine ptr = (*slot)->prelines;
|
||||
|
||||
for ( n = 0; n < outline->n_contours; n++ )
|
||||
{
|
||||
FT_TRACE5(( "ft_decompose_outline: Contour %d\n", n ));
|
||||
|
||||
first = last + 1;
|
||||
last = outline->contours[n];
|
||||
if ( last < first ){
|
||||
FT_TRACE5(( "Invalid Outline"));
|
||||
break;
|
||||
}
|
||||
limit = outline->points + last;
|
||||
|
||||
v_start = outline->points[first];
|
||||
|
||||
|
||||
v_last = outline->points[last];
|
||||
|
||||
v_control = v_start;
|
||||
|
||||
point = outline->points + first;
|
||||
tags = outline->tags + first;
|
||||
tag = FT_CURVE_TAG( tags[0] );
|
||||
|
||||
/* A contour cannot start with a cubic control point! */
|
||||
if ( tag == FT_CURVE_TAG_CUBIC )
|
||||
{
|
||||
FT_TRACE5(( "Invalid Outline"));
|
||||
break;
|
||||
}
|
||||
/* check first point to determine origin */
|
||||
if ( tag == FT_CURVE_TAG_CONIC )
|
||||
{
|
||||
/* first point is conic control. Yes, this happens. */
|
||||
if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
|
||||
{
|
||||
/* start at last point if it is on the curve */
|
||||
v_start = v_last;
|
||||
limit--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if both first and last points are conic, */
|
||||
/* start at their middle and record its position */
|
||||
/* for closure */
|
||||
v_start.x = ( v_start.x + v_last.x ) / 2;
|
||||
v_start.y = ( v_start.y + v_last.y ) / 2;
|
||||
|
||||
/* v_last = v_start; */
|
||||
}
|
||||
point--;
|
||||
tags--;
|
||||
}
|
||||
|
||||
FT_TRACE5(( " move to (%.2f, %.2f)\n",
|
||||
(double)v_start.x / 64, (double)v_start.y / 64 ));
|
||||
|
||||
|
||||
FT_PreLine pl = malloc(sizeof(FT_PreLineRec));
|
||||
pl->x1 = v_start.x;
|
||||
pl->y1 = v_start.y;
|
||||
pl->x2 = v_start.x;
|
||||
pl->y2 = v_start.y;
|
||||
pl->next = NULL;
|
||||
|
||||
if ( ( *slot )->prelines == NULL )
|
||||
{
|
||||
ptr = ( *slot )->prelines = pl;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->next = pl;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
while ( point < limit )
|
||||
{
|
||||
point++;
|
||||
tags++;
|
||||
|
||||
tag = FT_CURVE_TAG( tags[0] );
|
||||
switch ( tag )
|
||||
{
|
||||
case FT_CURVE_TAG_ON: /* emit a single line_to */
|
||||
{
|
||||
FT_Vector vec;
|
||||
|
||||
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
|
||||
FT_TRACE5(( " line to (%.2f, %.2f)\n",
|
||||
(double)vec.x / 64, (double)vec.y / 64 ));
|
||||
|
||||
FT_PreLine pl3 = malloc(sizeof(FT_PreLineRec));
|
||||
pl3->x1 = ptr->x2;
|
||||
pl3->y1 = ptr->y2;
|
||||
pl3->x2 = vec.x;
|
||||
pl3->y2 = vec.y;
|
||||
pl3->next = NULL;
|
||||
ptr->next = pl3;
|
||||
ptr = ptr->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
case FT_CURVE_TAG_CONIC: /* consume conic arcs */
|
||||
v_control.x = point->x ;
|
||||
v_control.y = point->y ;
|
||||
|
||||
Do_Conic:
|
||||
if ( point < limit )
|
||||
{
|
||||
FT_Vector vec;
|
||||
FT_Vector v_middle;
|
||||
|
||||
|
||||
point++;
|
||||
tags++;
|
||||
tag = FT_CURVE_TAG( tags[0] );
|
||||
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
|
||||
if ( tag == FT_CURVE_TAG_ON )
|
||||
{
|
||||
FT_TRACE5(( " conic to (%.2f, %.2f)"
|
||||
" with control (%.2f, %.2f)\n",
|
||||
(double)vec.x / 64,
|
||||
(double)vec.y / 64,
|
||||
(double)v_control.x / 64,
|
||||
(double)v_control.y / 64 ));
|
||||
FT_Vector vex0 = {ptr->x2, ptr->y2};
|
||||
error = conic_to2(slot, &v_control, &vex0,&vec , &ptr);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( tag != FT_CURVE_TAG_CONIC )
|
||||
{
|
||||
FT_TRACE5( ( "Invalid Outline" ) );
|
||||
break;
|
||||
}
|
||||
v_middle.x = ( v_control.x + vec.x ) / 2;
|
||||
v_middle.y = ( v_control.y + vec.y ) / 2;
|
||||
|
||||
FT_TRACE5(( " conic to (%.2f, %.2f)"
|
||||
" with control (%.2f, %.2f)\n",
|
||||
(double)v_middle.x / 64,
|
||||
(double)v_middle.y / 64,
|
||||
(double)v_control.x / 64,
|
||||
(double)v_control.y / 64 ));
|
||||
FT_Vector vex = {ptr->x2, ptr->y2};
|
||||
error = conic_to2(slot, &v_control, &vex,&v_middle, &ptr);
|
||||
|
||||
v_control = vec;
|
||||
goto Do_Conic;
|
||||
}
|
||||
|
||||
FT_TRACE5(( " conic to (%.2f, %.2f)"
|
||||
" with control (%.2f, %.2f)\n",
|
||||
(double)v_start.x / 64,
|
||||
(double)v_start.y / 64,
|
||||
(double)v_control.x / 64,
|
||||
(double)v_control.y / 64 ));
|
||||
FT_Vector vex2 = {ptr->x2, ptr->y2};
|
||||
error = conic_to2( slot, &v_control, &vex2, &v_start, &ptr );
|
||||
}
|
||||
}
|
||||
|
||||
/* close the contour with a line segment */
|
||||
FT_TRACE5(( " line to (%.2f, %.2f)\n",
|
||||
(double)v_start.x / 64, (double)v_start.y / 64 ));
|
||||
FT_PreLine pl2 = malloc(sizeof(FT_PreLineRec));
|
||||
pl2->x1 = ptr->x2;
|
||||
pl2->y1 = ptr->y2;
|
||||
pl2->x2 = v_start.x;
|
||||
pl2->y2 = v_start.y;
|
||||
pl2->next = NULL;
|
||||
ptr->next = pl2;
|
||||
ptr = ptr->next;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
ft_open_face_internal( FT_Library library,
|
||||
const FT_Open_Args* args,
|
||||
@ -2748,6 +3079,33 @@
|
||||
|
||||
face->size = size;
|
||||
}
|
||||
if ( args->size > 0 )
|
||||
{
|
||||
face->glyph_array = (FT_GlyphSlot*)malloc(
|
||||
face->driver->clazz->slot_object_size * face->num_glyphs );
|
||||
error = FT_Set_Pixel_Sizes( face, 0, args->size );
|
||||
|
||||
for ( int gindex = 0; gindex < face->num_glyphs; gindex++ )
|
||||
{
|
||||
driver = face->driver;
|
||||
FT_Driver_Class clazz = driver->clazz;
|
||||
memory = driver->root.memory;
|
||||
|
||||
FT_ALLOC( face->glyph_array[gindex], clazz->slot_object_size );
|
||||
|
||||
face->glyph_array[gindex]->face = face;
|
||||
face->glyph_array[gindex]->prel_shifted = 0;
|
||||
face->glyph_array[gindex]->glyph_index = gindex;
|
||||
ft_glyphslot_init( face->glyph_array[gindex] );
|
||||
|
||||
face->glyph_array[gindex]->next = NULL;
|
||||
*face->glyph = *face->glyph_array[gindex];
|
||||
|
||||
FT_Load_Glyph( face, gindex, FT_LOAD_NO_HINTING );
|
||||
|
||||
ft_decompose_outline( &face->glyph_array[gindex] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* some checks */
|
||||
|
6
src/dense/dense.c
Normal file
6
src/dense/dense.c
Normal file
@ -0,0 +1,6 @@
|
||||
/** For building a single object of the entire module */
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT
|
||||
|
||||
#include "ftdense.c"
|
||||
#include "ftdenserend.c"
|
||||
/* END */
|
741
src/dense/ftdense.c
Normal file
741
src/dense/ftdense.c
Normal file
@ -0,0 +1,741 @@
|
||||
/** The rasterizer for the 'dense' renderer */
|
||||
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT dense
|
||||
|
||||
#include <freetype/ftoutln.h>
|
||||
#include <freetype/internal/ftcalc.h>
|
||||
#include <freetype/internal/ftdebug.h>
|
||||
#include <freetype/internal/ftobjs.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "ftdense.h"
|
||||
#include "ftdenseerrs.h"
|
||||
|
||||
#if defined( __SSE4_1__ ) || \
|
||||
defined( __x86_64__ ) || \
|
||||
defined( _M_AMD64 ) || \
|
||||
( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 )
|
||||
#define FT_SSE4_1 1
|
||||
#else
|
||||
#define FT_SSE4_1 0
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_NEON)
|
||||
#define FT_NEON 1
|
||||
#else
|
||||
#define FT_NEON 0
|
||||
#endif
|
||||
|
||||
|
||||
#if FT_SSE4_1
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#elif FT_NEON
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define PIXEL_BITS 8
|
||||
|
||||
#define ONE_PIXEL ( 1 << PIXEL_BITS )
|
||||
#define TRUNC( x ) (int)( ( x ) >> PIXEL_BITS )
|
||||
|
||||
#define UPSCALE( x ) ( ( x ) * ( ONE_PIXEL >> 6 ) )
|
||||
#define DOWNSCALE( x ) ( ( x ) >> ( PIXEL_BITS - 6 ) )
|
||||
|
||||
#define FT_SWAP(a, b) { (a) = (a) + (b); (b) = (a) - (b); (a) = (a) - (b);}
|
||||
#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
|
||||
#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
|
||||
#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
|
||||
|
||||
// TODO: Fix types
|
||||
#define FT_UDIVPREP( c, b ) \
|
||||
FT26D6 b ## _r = c ? (FT26D6)0xFFFFFFFF / ( b ) : 0
|
||||
#define FT_UDIV( a, b ) \
|
||||
(FT26D6)( ( (FT26D6)( a ) * (FT26D6)( b ## _r ) ) >> 32 )
|
||||
|
||||
typedef struct dense_TRaster_
|
||||
{
|
||||
void* memory;
|
||||
|
||||
} dense_TRaster, *dense_PRaster;
|
||||
|
||||
/* Linear interpolation between P0 and P1 */
|
||||
static FT_Vector
|
||||
Lerp( float T, FT_Vector P0, FT_Vector P1 )
|
||||
{
|
||||
FT_Vector p;
|
||||
p.x = P0.x + T * ( P1.x - P0.x );
|
||||
p.y = P0.y + T * ( P1.y - P0.y );
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
dense_move_to( const FT_Vector* to, dense_worker* worker )
|
||||
{
|
||||
FT_Pos x, y;
|
||||
|
||||
x = UPSCALE( to->x );
|
||||
y = UPSCALE( to->y );
|
||||
worker->prev_x = x;
|
||||
worker->prev_y = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dense_line_to( const FT_Vector* to, dense_worker* worker )
|
||||
{
|
||||
dense_render_line( worker, UPSCALE( to->x ), UPSCALE( to->y ) );
|
||||
dense_move_to( to, worker );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dense_render_line2( dense_worker* worker, FT_PreLine pl )
|
||||
{
|
||||
|
||||
FT26D6 fx = UPSCALE(pl->x1)>>2;
|
||||
FT26D6 fy = UPSCALE(pl->y1)>>2;
|
||||
|
||||
FT26D6 from_x = fx;
|
||||
FT26D6 from_y = fy;
|
||||
|
||||
|
||||
FT26D6 tx = UPSCALE(pl->x2)>>2;
|
||||
FT26D6 ty = UPSCALE(pl->y2)>>2;
|
||||
|
||||
if ( fy == ty )
|
||||
return;
|
||||
|
||||
FT26D6 to_x = tx;
|
||||
FT26D6 to_y = ty;
|
||||
|
||||
int dir = 1;
|
||||
if ( from_y >= to_y )
|
||||
{
|
||||
dir = -1;
|
||||
FT_SWAP(from_x, to_x);
|
||||
FT_SWAP(from_y, to_y);
|
||||
}
|
||||
|
||||
// Clip to the height.
|
||||
if ( from_y >= worker->m_h<<6 || to_y <= 0 )
|
||||
return;
|
||||
|
||||
FT26D6 deltax,deltay;
|
||||
deltax = to_x - from_x;
|
||||
deltay = to_y - from_y;
|
||||
|
||||
FT_UDIVPREP(from_x != to_x, deltax);
|
||||
|
||||
FT_UDIVPREP(from_y != to_y, deltay);
|
||||
|
||||
if ( from_y < 0 )
|
||||
{
|
||||
from_x -= from_y * deltax/deltay;
|
||||
from_y = 0;
|
||||
}
|
||||
|
||||
if ( to_y > worker->m_h<<6 )
|
||||
{
|
||||
to_x -= (( to_y - worker->m_h<<6 ) * deltax/deltay);
|
||||
to_y = worker->m_h<<6;
|
||||
}
|
||||
|
||||
|
||||
if(deltax == 0){
|
||||
FT26D6 x = from_x;
|
||||
int x0i = x>>6;
|
||||
FT26D6 x0floor = x0i<<6;
|
||||
|
||||
// y-coordinate of first pixel of line
|
||||
int y0 = from_y>>6;
|
||||
|
||||
// y-coordinate of last pixel of line
|
||||
int y_limit = (to_y + 0x3f)>>6;
|
||||
FT20D12* m_a = worker->m_a;
|
||||
|
||||
|
||||
|
||||
for ( int y = y0; y < y_limit; y++ )
|
||||
{
|
||||
int linestart = y * worker->m_w;
|
||||
|
||||
FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
||||
|
||||
m_a[linestart + x0i] += dir*dy*(64 - x + x0floor);
|
||||
m_a[linestart + ( x0i + 1 )] += dir*dy*(x-x0floor);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = from_x;
|
||||
int y0 = from_y>>6;
|
||||
int y_limit = (to_y + 0x3f)>>6;
|
||||
|
||||
FT20D12* m_a = worker->m_a;
|
||||
|
||||
for ( int y = y0; y < y_limit; y++ )
|
||||
{
|
||||
int linestart = y * worker->m_w;
|
||||
FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
||||
FT26D6 xnext = x + FT_UDIV((dy*deltax), deltay);
|
||||
FT26D6 d = dy * dir;
|
||||
|
||||
FT26D6 x0, x1;
|
||||
if ( x < xnext )
|
||||
{
|
||||
x0 = x;
|
||||
x1 = xnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = xnext;
|
||||
x1 = x;
|
||||
}
|
||||
|
||||
|
||||
int x0i = x0>>6;
|
||||
FT26D6 x0floor = x0i<<6;
|
||||
|
||||
|
||||
int x1i = (x1+0x3f)>>6;
|
||||
FT26D6 x1ceil = x1i <<6;
|
||||
|
||||
if ( x1i <= x0i + 1 )
|
||||
{
|
||||
FT26D6 xmf = ( ( x + xnext )>>1) - x0floor;
|
||||
m_a[linestart + x0i] += d * ((1<<6) - xmf);
|
||||
m_a[linestart + ( x0i + 1 )] += d * xmf;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
FT26D6 oneOverS = x1 - x0;
|
||||
|
||||
FT_UDIVPREP(x1 != x0, oneOverS);
|
||||
|
||||
FT26D6 x0f = x0 - x0floor;
|
||||
|
||||
|
||||
FT26D6 oneMinusX0f = (1<<6) - x0f;
|
||||
FT26D6 a0 = FT_UDIV(((oneMinusX0f * oneMinusX0f) >> 1), oneOverS);
|
||||
FT26D6 x1f = x1 - x1ceil + (1<<6);
|
||||
FT26D6 am = FT_UDIV(((x1f * x1f) >> 1) , oneOverS);
|
||||
|
||||
m_a[linestart + x0i] += d * a0;
|
||||
|
||||
if ( x1i == x0i + 2 )
|
||||
m_a[linestart + ( x0i + 1 )] += d * ( (1<<6) - a0 - am );
|
||||
else
|
||||
{
|
||||
FT26D6 a1 = FT_UDIV((((1<<6) + (1<<5) - x0f) << 6) , oneOverS);
|
||||
m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
|
||||
|
||||
FT26D6 dTimesS = FT_UDIV((d << 12) , oneOverS);
|
||||
|
||||
for ( FT26D6 xi = x0i + 2; xi < x1i - 1; xi++ )
|
||||
m_a[linestart + xi] += dTimesS;
|
||||
|
||||
FT26D6 a2 = a1 + FT_UDIV((( x1i - x0i - 3 )<<12),oneOverS);
|
||||
m_a[linestart + ( x1i - 1 )] += d * ( (1<<6) - a2 - am );
|
||||
}
|
||||
m_a[linestart + x1i] += d * am;
|
||||
}
|
||||
x = xnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dense_render_line( dense_worker* worker, FT_Pos tox, FT_Pos toy )
|
||||
{
|
||||
|
||||
FT26D6 fx = worker->prev_x>>2;
|
||||
FT26D6 fy = worker->prev_y>>2;
|
||||
|
||||
FT26D6 from_x = fx;
|
||||
FT26D6 from_y = fy;
|
||||
|
||||
|
||||
FT26D6 tx = tox>>2;
|
||||
FT26D6 ty = toy>>2;
|
||||
|
||||
if ( fy == ty )
|
||||
return;
|
||||
|
||||
FT26D6 to_x = tx;
|
||||
FT26D6 to_y = ty;
|
||||
|
||||
int dir = 1;
|
||||
if ( from_y >= to_y )
|
||||
{
|
||||
dir = -1;
|
||||
FT_SWAP(from_x, to_x);
|
||||
FT_SWAP(from_y, to_y);
|
||||
}
|
||||
|
||||
// Clip to the height.
|
||||
if ( from_y >= worker->m_h<<6 || to_y <= 0 )
|
||||
return;
|
||||
|
||||
FT26D6 deltax,deltay;
|
||||
deltax = to_x - from_x;
|
||||
deltay = to_y - from_y;
|
||||
|
||||
FT_UDIVPREP(from_x != to_x, deltax);
|
||||
|
||||
FT_UDIVPREP(from_y != to_y, deltay);
|
||||
|
||||
if ( from_y < 0 )
|
||||
{
|
||||
from_x -= from_y * deltax/deltay;
|
||||
from_y = 0;
|
||||
}
|
||||
|
||||
if ( to_y > worker->m_h<<6 )
|
||||
{
|
||||
to_x -= (( to_y - worker->m_h<<6 ) * deltax/deltay);
|
||||
to_y = worker->m_h<<6;
|
||||
}
|
||||
|
||||
|
||||
if(deltax == 0){
|
||||
FT26D6 x = from_x;
|
||||
int x0i = x>>6;
|
||||
FT26D6 x0floor = x0i<<6;
|
||||
|
||||
// y-coordinate of first pixel of line
|
||||
int y0 = from_y>>6;
|
||||
|
||||
// y-coordinate of last pixel of line
|
||||
int y_limit = (to_y + 0x3f)>>6;
|
||||
FT20D12* m_a = worker->m_a;
|
||||
|
||||
|
||||
|
||||
for ( int y = y0; y < y_limit; y++ )
|
||||
{
|
||||
int linestart = y * worker->m_w;
|
||||
|
||||
FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
||||
|
||||
m_a[linestart + x0i] += dir*dy*(64 - x + x0floor);
|
||||
m_a[linestart + ( x0i + 1 )] += dir*dy*(x-x0floor);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = from_x;
|
||||
int y0 = from_y>>6;
|
||||
int y_limit = (to_y + 0x3f)>>6;
|
||||
|
||||
FT20D12* m_a = worker->m_a;
|
||||
|
||||
for ( int y = y0; y < y_limit; y++ )
|
||||
{
|
||||
int linestart = y * worker->m_w;
|
||||
FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
||||
FT26D6 xnext = x + FT_UDIV((dy*deltax), deltay);
|
||||
FT26D6 d = dy * dir;
|
||||
|
||||
FT26D6 x0, x1;
|
||||
if ( x < xnext )
|
||||
{
|
||||
x0 = x;
|
||||
x1 = xnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = xnext;
|
||||
x1 = x;
|
||||
}
|
||||
|
||||
|
||||
int x0i = x0>>6;
|
||||
FT26D6 x0floor = x0i<<6;
|
||||
|
||||
|
||||
int x1i = (x1+0x3f)>>6;
|
||||
FT26D6 x1ceil = x1i <<6;
|
||||
|
||||
if ( x1i <= x0i + 1 )
|
||||
{
|
||||
FT26D6 xmf = ( ( x + xnext )>>1) - x0floor;
|
||||
m_a[linestart + x0i] += d * ((1<<6) - xmf);
|
||||
m_a[linestart + ( x0i + 1 )] += d * xmf;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
FT26D6 oneOverS = x1 - x0;
|
||||
|
||||
FT_UDIVPREP(x1 != x0, oneOverS);
|
||||
|
||||
FT26D6 x0f = x0 - x0floor;
|
||||
|
||||
|
||||
FT26D6 oneMinusX0f = (1<<6) - x0f;
|
||||
FT26D6 a0 = FT_UDIV(((oneMinusX0f * oneMinusX0f) >> 1), oneOverS);
|
||||
FT26D6 x1f = x1 - x1ceil + (1<<6);
|
||||
FT26D6 am = FT_UDIV(((x1f * x1f) >> 1) , oneOverS);
|
||||
|
||||
m_a[linestart + x0i] += d * a0;
|
||||
|
||||
if ( x1i == x0i + 2 )
|
||||
m_a[linestart + ( x0i + 1 )] += d * ( (1<<6) - a0 - am );
|
||||
else
|
||||
{
|
||||
FT26D6 a1 = FT_UDIV((((1<<6) + (1<<5) - x0f) << 6) , oneOverS);
|
||||
m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
|
||||
|
||||
FT26D6 dTimesS = FT_UDIV((d << 12) , oneOverS);
|
||||
|
||||
for ( FT26D6 xi = x0i + 2; xi < x1i - 1; xi++ )
|
||||
m_a[linestart + xi] += dTimesS;
|
||||
|
||||
FT26D6 a2 = a1 + FT_UDIV((( x1i - x0i - 3 )<<12),oneOverS);
|
||||
m_a[linestart + ( x1i - 1 )] += d * ( (1<<6) - a2 - am );
|
||||
}
|
||||
m_a[linestart + x1i] += d * am;
|
||||
}
|
||||
x = xnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dense_conic_to( const FT_Vector* control,
|
||||
const FT_Vector* to,
|
||||
dense_worker* worker )
|
||||
{
|
||||
dense_render_quadratic( worker, control, to );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dense_render_quadratic( dense_worker* worker,
|
||||
FT_Vector* control,
|
||||
FT_Vector* to )
|
||||
{
|
||||
/*
|
||||
Calculate devsq as the square of four times the
|
||||
distance from the control point to the midpoint of the curve.
|
||||
This is the place at which the curve is furthest from the
|
||||
line joining the control points.
|
||||
|
||||
4 x point on curve = p0 + 2p1 + p2
|
||||
4 x midpoint = 4p1
|
||||
|
||||
The division by four is omitted to save time.
|
||||
*/
|
||||
|
||||
FT_Vector aP0 = { DOWNSCALE( worker->prev_x ), DOWNSCALE( worker->prev_y ) };
|
||||
FT_Vector aP1 = { control->x, control->y };
|
||||
FT_Vector aP2 = { to->x, to->y };
|
||||
|
||||
float devx = aP0.x - aP1.x - aP1.x + aP2.x;
|
||||
float devy = aP0.y - aP1.y - aP1.y + aP2.y;
|
||||
float devsq = devx * devx + devy * devy;
|
||||
|
||||
if ( devsq < 0.333f )
|
||||
{
|
||||
dense_line_to( &aP2, worker );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
According to Raph Levien, the reason for the subdivision by n (instead of
|
||||
recursive division by the Casteljau system) is that "I expect the flatness
|
||||
computation to be semi-expensive (it's done once rather than on each potential
|
||||
subdivision) and also because you'll often get fewer subdivisions. Taking a
|
||||
circular arc as a simplifying assumption, where I get n, a recursive approach
|
||||
would get 2^ceil(lg n), which, if I haven't made any horrible mistakes, is
|
||||
expected to be 33% more in the limit".
|
||||
*/
|
||||
|
||||
const float tol = 3.0f;
|
||||
int n = (int)floor( sqrt( sqrt( tol * devsq ) ) )/8;
|
||||
FT_Vector p = aP0;
|
||||
float nrecip = 1.0f / ( n + 1.0f );
|
||||
float t = 0.0f;
|
||||
for ( int i = 0; i < n; i++ )
|
||||
{
|
||||
t += nrecip;
|
||||
FT_Vector next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
|
||||
dense_line_to(&next, worker );
|
||||
p = next;
|
||||
}
|
||||
|
||||
dense_line_to( &aP2, worker );
|
||||
}
|
||||
|
||||
static int
|
||||
dense_cubic_to( const FT_Vector* control1,
|
||||
const FT_Vector* control2,
|
||||
const FT_Vector* to,
|
||||
dense_worker* worker )
|
||||
{
|
||||
dense_render_cubic( worker, control1, control2, to );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dense_render_cubic( dense_worker* worker,
|
||||
FT_Vector* control_1,
|
||||
FT_Vector* control_2,
|
||||
FT_Vector* to )
|
||||
{
|
||||
FT_Vector aP0 = { DOWNSCALE( worker->prev_x ), DOWNSCALE( worker->prev_y ) };
|
||||
FT_Vector aP1 = { control_1->x, control_1->y };
|
||||
FT_Vector aP2 = { control_2->x, control_2->y };
|
||||
FT_Vector aP3 = { to->x, to->y };
|
||||
|
||||
float devx = aP0.x - aP1.x - aP1.x + aP2.x;
|
||||
float devy = aP0.y - aP1.y - aP1.y + aP2.y;
|
||||
float devsq0 = devx * devx + devy * devy;
|
||||
devx = aP1.x - aP2.x - aP2.x + aP3.x;
|
||||
devy = aP1.y - aP2.y - aP2.y + aP3.y;
|
||||
float devsq1 = devx * devx + devy * devy;
|
||||
float devsq = fmax( devsq0, devsq1 );
|
||||
|
||||
if ( devsq < 0.333f )
|
||||
{
|
||||
dense_render_line( worker, aP3.x, aP3.y );
|
||||
return;
|
||||
}
|
||||
|
||||
const float tol = 3.0f;
|
||||
int n = (int)floor( sqrt( sqrt( tol * devsq ) ) ) / 8;
|
||||
FT_Vector p = aP0;
|
||||
float nrecip = 1.0f / ( n + 1.0f );
|
||||
float t = 0.0f;
|
||||
for ( int i = 0; i < n; i++ )
|
||||
{
|
||||
t += nrecip;
|
||||
FT_Vector a = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
|
||||
FT_Vector b = Lerp( t, Lerp( t, aP1, aP2 ), Lerp( t, aP2, aP3 ) );
|
||||
FT_Vector next = Lerp( t, a, b );
|
||||
dense_render_line( worker, next.x, next.y );
|
||||
worker->prev_x = next.x;
|
||||
worker->prev_y = next.y;
|
||||
p = next;
|
||||
}
|
||||
|
||||
dense_line_to( &aP3, worker );
|
||||
}
|
||||
|
||||
static int
|
||||
dense_raster_new( FT_Memory memory, dense_PRaster* araster )
|
||||
{
|
||||
FT_Error error;
|
||||
dense_PRaster raster;
|
||||
|
||||
if ( !FT_NEW( raster ) )
|
||||
raster->memory = memory;
|
||||
|
||||
*araster = raster;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
dense_raster_done( FT_Raster raster )
|
||||
{
|
||||
FT_Memory memory = (FT_Memory)( (dense_PRaster)raster )->memory;
|
||||
|
||||
FT_FREE( raster );
|
||||
}
|
||||
|
||||
static void
|
||||
dense_raster_reset( FT_Raster raster,
|
||||
unsigned char* pool_base,
|
||||
unsigned long pool_size )
|
||||
{
|
||||
FT_UNUSED( raster );
|
||||
FT_UNUSED( pool_base );
|
||||
FT_UNUSED( pool_size );
|
||||
}
|
||||
|
||||
static int
|
||||
dense_raster_set_mode( FT_Raster raster, unsigned long mode, void* args )
|
||||
{
|
||||
FT_UNUSED( raster );
|
||||
FT_UNUSED( mode );
|
||||
FT_UNUSED( args );
|
||||
|
||||
return 0; /* nothing to do */
|
||||
}
|
||||
|
||||
FT_DEFINE_OUTLINE_FUNCS( dense_decompose_funcs,
|
||||
|
||||
(FT_Outline_MoveTo_Func)dense_move_to, /* move_to */
|
||||
(FT_Outline_LineTo_Func)dense_line_to, /* line_to */
|
||||
(FT_Outline_ConicTo_Func)dense_conic_to, /* conic_to */
|
||||
(FT_Outline_CubicTo_Func)dense_cubic_to, /* cubic_to */
|
||||
|
||||
0, /* shift */
|
||||
0 /* delta */
|
||||
)
|
||||
|
||||
static int
|
||||
dense_render_glyph( dense_worker* worker, const FT_Bitmap* target, FT_PreLine pl )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
|
||||
while (pl != NULL)
|
||||
{
|
||||
dense_render_line2(worker, pl);
|
||||
pl = pl->next;
|
||||
}
|
||||
|
||||
// Render into bitmap
|
||||
const FT20D12* source = worker->m_a;
|
||||
unsigned char* dest = target->buffer;
|
||||
unsigned char* dest_end = target->buffer + worker->m_w * worker->m_h;
|
||||
|
||||
#if FT_SSE4_1
|
||||
|
||||
__m128i offset = _mm_setzero_si128();
|
||||
__m128i nzero = _mm_castps_si128(_mm_set1_ps(-0.0));
|
||||
|
||||
for (int i = 0; i < worker->m_h*worker->m_w; i += 4)
|
||||
{
|
||||
// load 4 floats from source
|
||||
|
||||
__m128i x = _mm_load_si128( (__m128i*)&source[i] );
|
||||
|
||||
x = _mm_add_epi32( x, _mm_slli_si128( x, 4 ) );
|
||||
|
||||
x = _mm_add_epi32( x, _mm_slli_si128( x, 8 ) );
|
||||
|
||||
// add the prefix sum of previous 4 ints to all ints
|
||||
x = _mm_add_epi32( x, offset );
|
||||
|
||||
// take absolute value
|
||||
__m128i y = _mm_srli_epi32( _mm_abs_epi32( x) , 4 );
|
||||
y = _mm_packus_epi16(_mm_packs_epi32(y, nzero), nzero);
|
||||
_mm_storeu_si32(&dest[i], y);
|
||||
|
||||
// store the current prefix sum in offset
|
||||
offset = _mm_shuffle_epi32(x,_MM_SHUFFLE( 3, 3, 3, 3 ) );
|
||||
}
|
||||
#elif FT_NEON
|
||||
int32x4_t offset = vdupq_n_s32(0);
|
||||
int32x4_t nzero = vreinterpretq_s32_f32(vdupq_n_f32(-0.0));
|
||||
|
||||
for (int i = 0; i < worker->m_h*worker->m_w; i += 4)
|
||||
{
|
||||
// load 4 floats from source
|
||||
|
||||
int32x4_t x = vld1q_s32( (int32_t*)&source[i] );
|
||||
|
||||
x = vaddq_s32( x, vreinterpretq_s32_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_s32( x), 12) ));
|
||||
|
||||
x = vaddq_s32(x, vreinterpretq_s32_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_s32(x), 8)));
|
||||
|
||||
// add the prefsum of previous 4 floats to all current floats
|
||||
x = vaddq_s32( x, offset );
|
||||
|
||||
int32x4_t y = vshrq_n_s32( vabsq_s32( x) , 4 );
|
||||
y = vreinterpretq_s32_s16(vcombine_s16(vqmovn_s32(y), vqmovn_s32(nzero)));
|
||||
y = vreinterpretq_s32_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_s32(y)), vqmovun_s16(vreinterpretq_s16_s32(nzero))));
|
||||
|
||||
vst1q_s32(&dest[i], y);
|
||||
|
||||
offset = vdupq_laneq_s32(x,3 );
|
||||
}
|
||||
#else
|
||||
|
||||
FT20D12 value = 0;
|
||||
|
||||
while ( dest < dest_end )
|
||||
{
|
||||
value += *source++;
|
||||
|
||||
if(value > 0){
|
||||
int n = value >>4;
|
||||
|
||||
if(n>255)n=255;
|
||||
*dest = (unsigned char)n;
|
||||
}else{
|
||||
*dest = 0;
|
||||
}
|
||||
dest++;
|
||||
}
|
||||
|
||||
#endif /* FT_SSE4_1 || FT_NEON */
|
||||
|
||||
free(worker->m_a);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
dense_raster_render( FT_Raster raster, const FT_Raster_Params* params )
|
||||
{
|
||||
const FT_Outline* outline = (const FT_Outline*)params->source;
|
||||
FT_Bitmap* target_map = params->target;
|
||||
FT_PreLine pl = params->prelines;
|
||||
|
||||
dense_worker worker[1];
|
||||
|
||||
if ( !raster )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
if ( !outline )
|
||||
return FT_THROW( Invalid_Outline );
|
||||
|
||||
worker->outline = *outline;
|
||||
|
||||
if ( !target_map )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
/* nothing to do */
|
||||
if ( !target_map->width || !target_map->rows )
|
||||
return 0;
|
||||
|
||||
if ( !target_map->buffer )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
worker->m_origin_x = 0;
|
||||
worker->m_origin_y = 0;
|
||||
worker->m_w = target_map->pitch;
|
||||
worker->m_h = target_map->rows;
|
||||
|
||||
int size = (worker->m_w * worker->m_h + 3) & ~3;
|
||||
|
||||
worker->m_a = malloc( sizeof( FT20D12 ) * size );
|
||||
worker->m_a_size = size;
|
||||
|
||||
memset( worker->m_a, 0, ( sizeof( FT20D12 ) * size ) );
|
||||
/* exit if nothing to do */
|
||||
if ( worker->m_w <= worker->m_origin_x || worker->m_h <= worker->m_origin_y )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invert the pitch to account for different +ve y-axis direction in dense array
|
||||
// (maybe temporary solution)
|
||||
target_map->pitch *= -1;
|
||||
return dense_render_glyph( worker, target_map, pl );
|
||||
}
|
||||
|
||||
FT_DEFINE_RASTER_FUNCS(
|
||||
ft_dense_raster,
|
||||
|
||||
FT_GLYPH_FORMAT_OUTLINE,
|
||||
|
||||
(FT_Raster_New_Func)dense_raster_new, /* raster_new */
|
||||
(FT_Raster_Reset_Func)dense_raster_reset, /* raster_reset */
|
||||
(FT_Raster_Set_Mode_Func)dense_raster_set_mode, /* raster_set_mode */
|
||||
(FT_Raster_Render_Func)dense_raster_render, /* raster_render */
|
||||
(FT_Raster_Done_Func)dense_raster_done /* raster_done */
|
||||
)
|
||||
|
||||
/* END */
|
63
src/dense/ftdense.h
Normal file
63
src/dense/ftdense.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* Dense rasterizer header*/
|
||||
|
||||
#ifndef FTDENSE_H_
|
||||
#define FTDENSE_H_
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CONFIG_CONFIG_H
|
||||
#include <freetype/ftimage.h>
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
#ifndef FT_EXPORT_VAR
|
||||
#define FT_EXPORT_VAR( x ) extern x
|
||||
#endif
|
||||
FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_dense_raster;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
typedef signed long FT26D6; /* 26.6 fixed-point representation */
|
||||
typedef signed int FT20D12; /* 20.12 fixed-point representation */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** The array used to store signed area differences. */
|
||||
FT20D12* m_a;
|
||||
/** The number of elements in m_a. */
|
||||
int m_a_size;
|
||||
/** The width of the current raster in pixels. */
|
||||
int m_w;
|
||||
/** The height of the current raster in pixels. */
|
||||
int m_h;
|
||||
/** The x origin of the raster. */
|
||||
int m_origin_x;
|
||||
/** The y origin of the raster. */
|
||||
int m_origin_y;
|
||||
|
||||
FT_Pos prev_x, prev_y;
|
||||
|
||||
FT_Outline outline;
|
||||
} dense_worker;
|
||||
|
||||
void dense_render_line( dense_worker* worker, FT_Pos to_x, FT_Pos to_y );
|
||||
void dense_render_quadratic( dense_worker* worker,
|
||||
FT_Vector* control,
|
||||
FT_Vector* to );
|
||||
void dense_render_cubic( dense_worker* worker,
|
||||
FT_Vector* control_1,
|
||||
FT_Vector* control_2,
|
||||
FT_Vector* to );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* FTDENSE_H_ */
|
||||
|
||||
/* END */
|
17
src/dense/ftdenseerrs.h
Normal file
17
src/dense/ftdenseerrs.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* Dense Renderer Error Codes */
|
||||
#ifndef FTDENSEERRS_H_
|
||||
#define FTDENSEERRS_H_
|
||||
|
||||
#include <freetype/ftmoderr.h>
|
||||
|
||||
#undef FTERRORS_H_
|
||||
|
||||
#undef FT_ERR_PREFIX
|
||||
#define FT_ERR_PREFIX Dense_Err_
|
||||
#define FT_ERR_BASE FT_Mod_Err_Dense
|
||||
|
||||
#include <freetype/fterrors.h>
|
||||
|
||||
#endif /* FTDENSEERRS_H_ */
|
||||
|
||||
/* END */
|
234
src/dense/ftdenserend.c
Normal file
234
src/dense/ftdenserend.c
Normal file
@ -0,0 +1,234 @@
|
||||
/** The 'dense' renderer */
|
||||
|
||||
#include <freetype/ftoutln.h>
|
||||
#include <freetype/internal/ftdebug.h>
|
||||
#include <freetype/internal/ftobjs.h>
|
||||
#include "ftdenserend.h"
|
||||
#include "ftdense.h"
|
||||
|
||||
#include "ftdenseerrs.h"
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* The macro FT_COMPONENT is used in trace mode. It is an implicit
|
||||
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
|
||||
* messages during execution.
|
||||
*/
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT dense
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* interface functions
|
||||
*
|
||||
*/
|
||||
|
||||
/* set render specific modes or attributes */
|
||||
static FT_Error
|
||||
ft_dense_set_mode( FT_Renderer render, FT_ULong mode_tag, FT_Pointer data )
|
||||
{
|
||||
/* pass it to the rasterizer */
|
||||
return render->clazz->raster_class->raster_set_mode( render->raster, mode_tag,
|
||||
data );
|
||||
}
|
||||
|
||||
/* transform the glyph using matrix and/or delta */
|
||||
static FT_Error
|
||||
ft_dense_transform( FT_Renderer render,
|
||||
FT_GlyphSlot slot,
|
||||
const FT_Matrix* matrix,
|
||||
const FT_Vector* delta )
|
||||
{
|
||||
|
||||
FT_Error error = FT_Err_Ok;
|
||||
|
||||
if ( slot->format != render->glyph_format )
|
||||
{
|
||||
error = FT_THROW( Invalid_Argument );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( matrix )
|
||||
FT_Outline_Transform( &slot->outline, matrix );
|
||||
|
||||
if ( delta )
|
||||
FT_Outline_Translate( &slot->outline, delta->x, delta->y );
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/* return the control box of a glyph's outline */
|
||||
static void
|
||||
ft_dense_get_cbox( FT_Renderer render, FT_GlyphSlot slot, FT_BBox* cbox )
|
||||
{
|
||||
|
||||
FT_ZERO( cbox );
|
||||
|
||||
if ( slot->format == render->glyph_format )
|
||||
FT_Outline_Get_CBox( &slot->outline, cbox );
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
ft_dense_init( FT_Renderer render )
|
||||
{
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
static void
|
||||
ft_dense_done( FT_Renderer render )
|
||||
{
|
||||
FT_UNUSED( render );
|
||||
}
|
||||
|
||||
/* generate bitmap from a glyph's slot image */
|
||||
static FT_Error
|
||||
ft_dense_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;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
|
||||
/* FT_FREE and FT_ALLOC_MULT macros need a variable named 'memory' */
|
||||
FT_Memory memory = render->root.memory;
|
||||
|
||||
FT_Pos x_shift = 0;
|
||||
FT_Pos y_shift = 0;
|
||||
|
||||
FT_Raster_Params params;
|
||||
|
||||
/* check whether slot format is correct before rendering */
|
||||
if ( slot->format != render->glyph_format )
|
||||
{
|
||||
error = FT_THROW( Invalid_Glyph_Format );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* check 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;
|
||||
}
|
||||
|
||||
|
||||
/* deallocate the previously allocated bitmap */
|
||||
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
FT_FREE( bitmap->buffer );
|
||||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
}
|
||||
|
||||
/* preset the bitmap using the glyph's outline */
|
||||
if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) )
|
||||
{
|
||||
error = FT_THROW( Raster_Overflow );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( !bitmap->rows || !bitmap->pitch )
|
||||
goto Exit;
|
||||
|
||||
|
||||
/* allocate new one */
|
||||
// ARM NEON crashes if memory is not aligned
|
||||
if ( FT_ALLOC_MULT( bitmap->buffer, 1,bitmap->rows*bitmap->pitch + 16 ) )
|
||||
goto Exit;
|
||||
|
||||
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
|
||||
|
||||
/* Calculate shift in 26.6 format */
|
||||
x_shift = 64 * -slot->bitmap_left;
|
||||
y_shift = 64 * -slot->bitmap_top;
|
||||
|
||||
if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
|
||||
y_shift += 64 * (FT_Int)bitmap->rows / 3;
|
||||
else
|
||||
y_shift += 64 * (FT_Int)bitmap->rows;
|
||||
|
||||
|
||||
if ( origin )
|
||||
{
|
||||
x_shift += origin->x;
|
||||
y_shift += origin->y;
|
||||
}
|
||||
|
||||
/* translate outline to render it into the bitmap */
|
||||
if ( (x_shift || y_shift) && !slot->prel_shifted){
|
||||
//FT_Outline_Translate( outline, x_shift, y_shift );
|
||||
FT_PreLine pl = slot->prelines;
|
||||
while (pl!=NULL)
|
||||
{
|
||||
pl->x1 += x_shift;
|
||||
pl->y1 += y_shift;
|
||||
pl->x2 += x_shift;
|
||||
pl->y2 += y_shift;
|
||||
|
||||
pl = pl->next;
|
||||
}
|
||||
slot->prel_shifted = 1;
|
||||
}
|
||||
|
||||
/* set up parameters */
|
||||
params.target = bitmap;
|
||||
params.source = outline;
|
||||
params.prelines = slot->prelines;
|
||||
|
||||
/* render the outline */
|
||||
error =
|
||||
render->raster_render( render->raster, (const FT_Raster_Params*)¶ms );
|
||||
|
||||
Exit:
|
||||
if ( !error )
|
||||
{
|
||||
/* the glyph is successfully rendered to a bitmap */
|
||||
slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
}
|
||||
else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
FT_FREE( bitmap->buffer );
|
||||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
}
|
||||
|
||||
// if ( x_shift || y_shift )
|
||||
// FT_Outline_Translate( outline, -x_shift, -y_shift );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_DEFINE_RENDERER(
|
||||
ft_dense_renderer_class,
|
||||
|
||||
FT_MODULE_RENDERER,
|
||||
sizeof( FT_RendererRec ),
|
||||
|
||||
"dense",
|
||||
0x10000L,
|
||||
0x20000L,
|
||||
|
||||
NULL,
|
||||
|
||||
(FT_Module_Constructor)ft_dense_init,
|
||||
(FT_Module_Destructor)ft_dense_done,
|
||||
(FT_Module_Requester)NULL,
|
||||
|
||||
FT_GLYPH_FORMAT_OUTLINE,
|
||||
|
||||
(FT_Renderer_RenderFunc)ft_dense_render, /* render_glyph */
|
||||
(FT_Renderer_TransformFunc)ft_dense_transform, /* transform_glyph */
|
||||
(FT_Renderer_GetCBoxFunc)ft_dense_get_cbox, /* get_glyph_cbox */
|
||||
(FT_Renderer_SetModeFunc)ft_dense_set_mode, /* set_mode */
|
||||
|
||||
(FT_Raster_Funcs*)&ft_dense_raster /* raster_class */
|
||||
)
|
||||
|
||||
/* END */
|
27
src/dense/ftdenserend.h
Normal file
27
src/dense/ftdenserend.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Dense renderer interface (specification) */
|
||||
#ifndef FTDENSEREND_H_
|
||||
#define FTDENSEREND_H_
|
||||
|
||||
|
||||
#include <freetype/ftmodapi.h>
|
||||
#include <freetype/ftrender.h>
|
||||
#include <freetype/internal/ftobjs.h>
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @renderer:
|
||||
* ft_dense_renderer_class
|
||||
*
|
||||
* @description:
|
||||
* Renderer to convert @FT_Outline to bitmaps.
|
||||
*
|
||||
*/
|
||||
FT_DECLARE_RENDERER( ft_dense_renderer_class )
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* FTDENSEREND_H_ */
|
||||
|
||||
/* END */
|
23
src/dense/module.mk
Normal file
23
src/dense/module.mk
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# FreeType 2 smooth renderer module definition
|
||||
#
|
||||
|
||||
|
||||
# Copyright (C) 1996-2021 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.
|
||||
|
||||
|
||||
FTMODULE_H_COMMANDS += DENSE_RENDERER
|
||||
|
||||
define DENSE_RENDERER
|
||||
$(OPEN_DRIVER) FT_Renderer_Class, ft_dense_renderer_class $(CLOSE_DRIVER)
|
||||
$(ECHO_DRIVER)dense $(ECHO_DRIVER_DESC)anti-aliased dense renderer$(ECHO_DRIVER_DONE)
|
||||
endef
|
||||
|
||||
# EOF
|
73
src/dense/rules.mk
Normal file
73
src/dense/rules.mk
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# FreeType 2 DENSE renderer module build rules
|
||||
#
|
||||
|
||||
|
||||
# Copyright (C) 1996-2021 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.
|
||||
|
||||
|
||||
# DENSE driver directory
|
||||
#
|
||||
DENSE_DIR := $(SRC_DIR)/dense
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
DENSE_COMPILE := $(CC) $(ANSIFLAGS) \
|
||||
$I$(subst /,$(COMPILER_SEP),$(DENSE_DIR)) \
|
||||
$(INCLUDE_FLAGS) \
|
||||
$(FT_CFLAGS) \
|
||||
"-march=native"
|
||||
|
||||
# DENSE driver sources (i.e., C files)
|
||||
#
|
||||
DENSE_DRV_SRC := $(DENSE_DIR)/ftdense.c \
|
||||
$(DENSE_DIR)/ftdenserend.c
|
||||
|
||||
|
||||
# DENSE driver headers
|
||||
#
|
||||
DENSE_DRV_H := $(DENSE_DRV_SRC:%c=%h) \
|
||||
$(DENSE_DIR)/ftdenseerrs.h
|
||||
|
||||
|
||||
# DENSE driver object(s)
|
||||
#
|
||||
# DENSE_DRV_OBJ_M is used during `multi' builds.
|
||||
# DENSE_DRV_OBJ_S is used during `single' builds.
|
||||
#
|
||||
DENSE_DRV_OBJ_M := $(DENSE_DRV_SRC:$(DENSE_DIR)/%.c=$(OBJ_DIR)/%.$O)
|
||||
DENSE_DRV_OBJ_S := $(OBJ_DIR)/dense.$O
|
||||
|
||||
# DENSE driver source file for single build
|
||||
#
|
||||
DENSE_DRV_SRC_S := $(DENSE_DIR)/dense.c
|
||||
|
||||
|
||||
# DENSE driver - single object
|
||||
#
|
||||
$(DENSE_DRV_OBJ_S): $(DENSE_DRV_SRC_S) $(DENSE_DRV_SRC) \
|
||||
$(FREETYPE_H) $(DENSE_DRV_H)
|
||||
$(DENSE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(DENSE_DRV_SRC_S))
|
||||
|
||||
|
||||
# DENSE driver - multiple objects
|
||||
#
|
||||
$(OBJ_DIR)/%.$O: $(DENSE_DIR)/%.c $(FREETYPE_H) $(DENSE_DRV_H)
|
||||
$(DENSE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(DENSE_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(DENSE_DRV_OBJ_M)
|
||||
|
||||
|
||||
# EOF
|
Loading…
Reference in New Issue
Block a user