summaryrefslogtreecommitdiffstats
path: root/src/smooth
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-03-03 14:24:57 -0800
committerDavid 'Digit' Turner <digit@google.com>2010-03-03 15:33:53 -0800
commit295ffce55e0198e7a9f7d46b33f5c2b4147bf821 (patch)
treebda1a337e630483e46b2e4d4db803814437b765d /src/smooth
parent6fb02c1f75ab969890012dd1f01939d3444ddbc1 (diff)
downloadandroid_external_freetype-295ffce55e0198e7a9f7d46b33f5c2b4147bf821.tar.gz
android_external_freetype-295ffce55e0198e7a9f7d46b33f5c2b4147bf821.tar.bz2
android_external_freetype-295ffce55e0198e7a9f7d46b33f5c2b4147bf821.zip
Update to FreeType 2.3.12
Diffstat (limited to 'src/smooth')
-rw-r--r--src/smooth/ftgrays.c137
-rw-r--r--src/smooth/ftgrays.h1
-rw-r--r--src/smooth/ftsmooth.c64
-rw-r--r--src/smooth/ftsmooth.h8
-rw-r--r--src/smooth/ftspic.c97
-rw-r--r--src/smooth/ftspic.h50
-rw-r--r--src/smooth/smooth.c1
7 files changed, 277 insertions, 81 deletions
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 10fa2ae..846e454 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008 by */
+/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -170,6 +170,34 @@
#endif /* !FT_DEBUG_LEVEL_TRACE */
+#define FT_DEFINE_OUTLINE_FUNCS( class_, \
+ move_to_, line_to_, \
+ conic_to_, cubic_to_, \
+ shift_, delta_ ) \
+ static const FT_Outline_Funcs class_ = \
+ { \
+ move_to_, \
+ line_to_, \
+ conic_to_, \
+ cubic_to_, \
+ shift_, \
+ delta_ \
+ };
+
+#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \
+ raster_new_, raster_reset_, \
+ raster_set_mode_, raster_render_, \
+ raster_done_ ) \
+ const FT_Raster_Funcs class_ = \
+ { \
+ glyph_format_, \
+ raster_new_, \
+ raster_reset_, \
+ raster_set_mode_, \
+ raster_render_, \
+ raster_done_ \
+ };
+
#else /* !_STANDALONE_ */
@@ -181,6 +209,8 @@
#include "ftsmerrs.h"
+#include "ftspic.h"
+
#define ErrRaster_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
#define ErrRaster_Invalid_Outline Smooth_Err_Invalid_Outline
#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
@@ -188,7 +218,6 @@
#endif /* !_STANDALONE_ */
-
#ifndef FT_MEM_SET
#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
#endif
@@ -201,27 +230,19 @@
#ifndef FT_STATIC_RASTER
-
#define RAS_ARG PWorker worker
#define RAS_ARG_ PWorker worker,
#define RAS_VAR worker
#define RAS_VAR_ worker,
-#define ras (*worker)
-
-
#else /* FT_STATIC_RASTER */
-
#define RAS_ARG /* empty */
#define RAS_ARG_ /* empty */
#define RAS_VAR /* empty */
#define RAS_VAR_ /* empty */
- static TWorker ras;
-
-
#endif /* FT_STATIC_RASTER */
@@ -254,7 +275,7 @@
/* need to define them to "float" or "double" when experimenting with */
/* new algorithms */
- typedef int TCoord; /* integer scanline/pixel coordinate */
+ typedef long TCoord; /* integer scanline/pixel coordinate */
typedef long TPos; /* sub-pixel coordinate */
/* determine the type used to store cell areas. This normally takes at */
@@ -285,8 +306,8 @@
typedef struct TCell_
{
- int x;
- int cover;
+ TPos x; /* same with TWorker.ex */
+ TCoord cover; /* same with TWorker.cover */
TArea area;
PCell next;
@@ -301,12 +322,12 @@
TPos count_ex, count_ey;
TArea area;
- int cover;
+ TCoord cover;
int invalid;
PCell cells;
- int max_cells;
- int num_cells;
+ FT_PtrDist max_cells;
+ FT_PtrDist num_cells;
TCoord cx, cy;
TPos x, y;
@@ -338,11 +359,18 @@
long buffer_size;
PCell* ycells;
- int ycount;
+ TPos ycount;
} TWorker, *PWorker;
+#ifndef FT_STATIC_RASTER
+#define ras (*worker)
+#else
+ static TWorker ras;
+#endif
+
+
typedef struct TRaster_
{
void* buffer;
@@ -428,7 +456,7 @@
gray_find_cell( RAS_ARG )
{
PCell *pcell, cell;
- int x = ras.ex;
+ TPos x = ras.ex;
if ( x > ras.count_ex )
@@ -560,9 +588,9 @@
TPos x2,
TCoord y2 )
{
- TCoord ex1, ex2, fx1, fx2, delta;
+ TCoord ex1, ex2, fx1, fx2, delta, mod, lift, rem;
long p, first, dx;
- int incr, lift, mod, rem;
+ int incr;
dx = x2 - x1;
@@ -584,7 +612,7 @@
if ( ex1 == ex2 )
{
delta = y2 - y1;
- ras.area += (TArea)( fx1 + fx2 ) * delta;
+ ras.area += (TArea)(( fx1 + fx2 ) * delta);
ras.cover += delta;
return;
}
@@ -612,7 +640,7 @@
mod += (TCoord)dx;
}
- ras.area += (TArea)( fx1 + first ) * delta;
+ ras.area += (TArea)(( fx1 + first ) * delta);
ras.cover += delta;
ex1 += incr;
@@ -642,7 +670,7 @@
delta++;
}
- ras.area += (TArea)ONE_PIXEL * delta;
+ ras.area += (TArea)(ONE_PIXEL * delta);
ras.cover += delta;
y1 += delta;
ex1 += incr;
@@ -651,7 +679,7 @@
}
delta = y2 - y1;
- ras.area += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
+ ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
ras.cover += delta;
}
@@ -664,10 +692,10 @@
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
{
- TCoord ey1, ey2, fy1, fy2;
+ TCoord ey1, ey2, fy1, fy2, mod;
TPos dx, dy, x, x2;
long p, first;
- int delta, rem, mod, lift, incr;
+ int delta, rem, lift, incr;
ey1 = TRUNC( ras.last_ey );
@@ -711,7 +739,7 @@
{
TCoord ex = TRUNC( ras.x );
TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
- TPos area;
+ TArea area;
first = ONE_PIXEL;
@@ -726,7 +754,7 @@
ras.cover += delta;
ey1 += incr;
- gray_set_cell( &ras, ex, ey1 );
+ gray_set_cell( RAS_VAR_ ex, ey1 );
delta = (int)( first + first - ONE_PIXEL );
area = (TArea)two_fx * delta;
@@ -736,7 +764,7 @@
ras.cover += delta;
ey1 += incr;
- gray_set_cell( &ras, ex, ey1 );
+ gray_set_cell( RAS_VAR_ ex, ey1 );
}
delta = (int)( fy2 - ONE_PIXEL + first );
@@ -1104,13 +1132,13 @@
/* record current cell, if any */
- gray_record_cell( worker );
+ gray_record_cell( RAS_VAR );
/* start to a new position */
x = UPSCALE( to->x );
y = UPSCALE( to->y );
- gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
+ gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
worker->x = x;
worker->y = y;
@@ -1122,7 +1150,7 @@
gray_line_to( const FT_Vector* to,
PWorker worker )
{
- gray_render_line( worker, UPSCALE( to->x ), UPSCALE( to->y ) );
+ gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
return 0;
}
@@ -1132,7 +1160,7 @@
const FT_Vector* to,
PWorker worker )
{
- gray_render_conic( worker, control, to );
+ gray_render_conic( RAS_VAR_ control, to );
return 0;
}
@@ -1143,7 +1171,7 @@
const FT_Vector* to,
PWorker worker )
{
- gray_render_cubic( worker, control1, control2, to );
+ gray_render_cubic( RAS_VAR_ control1, control2, to );
return 0;
}
@@ -1203,7 +1231,7 @@
gray_hline( RAS_ARG_ TCoord x,
TCoord y,
TPos area,
- int acount )
+ TCoord acount )
{
FT_Span* span;
int count;
@@ -1243,6 +1271,10 @@
if ( x >= 32767 )
x = 32767;
+ /* FT_Span.y is an integer, so limit our coordinates appropriately */
+ if ( y >= FT_INT_MAX )
+ y = FT_INT_MAX;
+
if ( coverage )
{
/* see whether we can add this span to the current list */
@@ -1281,7 +1313,7 @@
#endif /* FT_DEBUG_LEVEL_TRACE */
ras.num_gray_spans = 0;
- ras.span_y = y;
+ ras.span_y = (int)y;
count = 0;
span = ras.gray_spans;
@@ -1317,7 +1349,7 @@
printf( "%3d:", yindex );
for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
- printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area );
+ printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
printf( "\n" );
}
}
@@ -1349,7 +1381,7 @@
for ( ; cell != NULL; cell = cell->next )
{
- TArea area;
+ TPos area;
if ( cell->x > x && cover != 0 )
@@ -1666,23 +1698,25 @@
} TBand;
-
- static int
- gray_convert_glyph_inner( RAS_ARG )
- {
- static
- const FT_Outline_Funcs func_interface =
- {
+ FT_DEFINE_OUTLINE_FUNCS(func_interface,
(FT_Outline_MoveTo_Func) gray_move_to,
(FT_Outline_LineTo_Func) gray_line_to,
(FT_Outline_ConicTo_Func)gray_conic_to,
(FT_Outline_CubicTo_Func)gray_cubic_to,
0,
0
- };
+ )
+
+ static int
+ gray_convert_glyph_inner( RAS_ARG )
+ {
volatile int error = 0;
+#ifdef FT_CONFIG_OPTION_PIC
+ FT_Outline_Funcs func_interface;
+ Init_Class_func_interface(&func_interface);
+#endif
if ( ft_setjmp( ras.jump_buffer ) == 0 )
{
@@ -1829,7 +1863,7 @@
if ( middle == bottom )
{
#ifdef FT_DEBUG_LEVEL_TRACE
- FT_TRACE7(( "gray_convert_glyph: Rotten glyph!\n" ));
+ FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
#endif
return 1;
}
@@ -1917,7 +1951,7 @@
ras.clip_box.yMax = 32767L;
}
- gray_init_cells( worker, raster->buffer, raster->buffer_size );
+ gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
ras.outline = *outline;
ras.num_cells = 0;
@@ -1937,7 +1971,7 @@
ras.render_span_data = &ras;
}
- return gray_convert_glyph( worker );
+ return gray_convert_glyph( RAS_VAR );
}
@@ -2037,8 +2071,7 @@
}
- const FT_Raster_Funcs ft_grays_raster =
- {
+ FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
FT_GLYPH_FORMAT_OUTLINE,
(FT_Raster_New_Func) gray_raster_new,
@@ -2046,7 +2079,7 @@
(FT_Raster_Set_Mode_Func)0,
(FT_Raster_Render_Func) gray_raster_render,
(FT_Raster_Done_Func) gray_raster_done
- };
+ )
/* END */
diff --git a/src/smooth/ftgrays.h b/src/smooth/ftgrays.h
index 2d40954..f20f55f 100644
--- a/src/smooth/ftgrays.h
+++ b/src/smooth/ftgrays.h
@@ -28,6 +28,7 @@
#include "ftimage.h"
#else
#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H /* for FT_CONFIG_OPTION_PIC */
#include FT_IMAGE_H
#endif
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index a6db504..eed6353 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -17,10 +17,12 @@
#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_OUTLINE_H
#include "ftsmooth.h"
#include "ftgrays.h"
+#include "ftspic.h"
#include "ftsmerrs.h"
@@ -153,7 +155,7 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
- /* allocate new one, depends on pixel format */
+ /* allocate new one */
pitch = width;
if ( hmul )
{
@@ -194,6 +196,19 @@
#endif
+#if FT_UINT_MAX > 0xFFFFU
+
+ /* Required check is ( pitch * height < FT_ULONG_MAX ), */
+ /* but we care realistic cases only. Always pitch <= width. */
+ if ( width > 0xFFFFU || height > 0xFFFFU )
+ {
+ FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
+ width, height ));
+ return Smooth_Err_Raster_Overflow;
+ }
+
+#endif
+
bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap->num_grays = 256;
bitmap->width = width;
@@ -310,12 +325,19 @@
FT_Outline_Translate( outline, x_shift, y_shift );
+ /*
+ * XXX: on 16bit system, we return an error for huge bitmap
+ * to prevent an overflow.
+ */
+ if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
+ return Smooth_Err_Invalid_Pixel_Size;
+
if ( error )
goto Exit;
slot->format = FT_GLYPH_FORMAT_BITMAP;
- slot->bitmap_left = x_left;
- slot->bitmap_top = y_top;
+ slot->bitmap_left = (FT_Int)x_left;
+ slot->bitmap_top = (FT_Int)y_top;
Exit:
if ( outline && origin )
@@ -376,10 +398,8 @@
}
- FT_CALLBACK_TABLE_DEF
- const FT_Renderer_Class ft_smooth_renderer_class =
- {
- {
+ FT_DEFINE_RENDERER(ft_smooth_renderer_class,
+
FT_MODULE_RENDERER,
sizeof( FT_RendererRec ),
@@ -392,7 +412,7 @@
(FT_Module_Constructor)ft_smooth_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
- },
+ ,
FT_GLYPH_FORMAT_OUTLINE,
@@ -401,14 +421,12 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
(FT_Renderer_SetModeFunc) ft_smooth_set_mode,
- (FT_Raster_Funcs*) &ft_grays_raster
- };
+ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
+ )
- FT_CALLBACK_TABLE_DEF
- const FT_Renderer_Class ft_smooth_lcd_renderer_class =
- {
- {
+ FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
+
FT_MODULE_RENDERER,
sizeof( FT_RendererRec ),
@@ -421,7 +439,7 @@
(FT_Module_Constructor)ft_smooth_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
- },
+ ,
FT_GLYPH_FORMAT_OUTLINE,
@@ -430,15 +448,11 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
(FT_Renderer_SetModeFunc) ft_smooth_set_mode,
- (FT_Raster_Funcs*) &ft_grays_raster
- };
+ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
+ )
+ FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
-
- FT_CALLBACK_TABLE_DEF
- const FT_Renderer_Class ft_smooth_lcdv_renderer_class =
- {
- {
FT_MODULE_RENDERER,
sizeof( FT_RendererRec ),
@@ -451,7 +465,7 @@
(FT_Module_Constructor)ft_smooth_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
- },
+ ,
FT_GLYPH_FORMAT_OUTLINE,
@@ -460,8 +474,8 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
(FT_Renderer_SetModeFunc) ft_smooth_set_mode,
- (FT_Raster_Funcs*) &ft_grays_raster
- };
+ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
+ )
/* END */
diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h
index 62cced4..3708790 100644
--- a/src/smooth/ftsmooth.h
+++ b/src/smooth/ftsmooth.h
@@ -28,15 +28,15 @@ FT_BEGIN_HEADER
#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_std_renderer_class;
+ FT_DECLARE_RENDERER( ft_std_renderer_class )
#endif
#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_renderer_class;
+ FT_DECLARE_RENDERER( ft_smooth_renderer_class )
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_renderer_class;
+ FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class )
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_v_renderer_class;
+ FT_DECLARE_RENDERER( ft_smooth_lcd_v_renderer_class )
#endif
diff --git a/src/smooth/ftspic.c b/src/smooth/ftspic.c
new file mode 100644
index 0000000..aa547fc
--- /dev/null
+++ b/src/smooth/ftspic.c
@@ -0,0 +1,97 @@
+/***************************************************************************/
+/* */
+/* ftspic.c */
+/* */
+/* The FreeType position independent code services for smooth module. */
+/* */
+/* Copyright 2009 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"
+
+#ifdef FT_CONFIG_OPTION_PIC
+
+ /* forward declaration of PIC init functions from ftgrays.c */
+ void FT_Init_Class_ft_grays_raster(FT_Raster_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;
+ 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);
+/*Exit:*/
+ if(error)
+ ft_smooth_renderer_class_pic_free(library);
+ 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/smooth/ftspic.h b/src/smooth/ftspic.h
new file mode 100644
index 0000000..c7e0ce9
--- /dev/null
+++ b/src/smooth/ftspic.h
@@ -0,0 +1,50 @@
+/***************************************************************************/
+/* */
+/* ftspic.h */
+/* */
+/* The FreeType position independent code services for smooth module. */
+/* */
+/* Copyright 2009 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__
+
+
+FT_BEGIN_HEADER
+
+#include FT_INTERNAL_PIC_H
+
+#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)
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTSPIC_H__ */
+
+
+/* END */
diff --git a/src/smooth/smooth.c b/src/smooth/smooth.c
index ff6be3e..a8ac51f 100644
--- a/src/smooth/smooth.c
+++ b/src/smooth/smooth.c
@@ -19,6 +19,7 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
+#include "ftspic.c"
#include "ftgrays.c"
#include "ftsmooth.c"