diff --git a/config/ftoption.h b/config/ftoption.h index 2caf98bc0..0a4134c1b 100644 --- a/config/ftoption.h +++ b/config/ftoption.h @@ -44,6 +44,24 @@ /*************************************************************************/ /*************************************************************************/ + /*************************************************************************/ + /* */ + /* Convenience functions support */ + /* */ + /* Some functions of the FreeType 2 API are provided as a convenience */ + /* for client applications and developers. However, they are not */ + /* required to build and run the library itself. */ + /* */ + /* By defining this configuration macro, you'll disable the */ + /* compilation of these functions at build time. This can be useful */ + /* to reduce the library's code size when you don't need any of */ + /* these functions.. */ + /* */ + /* All convenience functions are declared as such in their */ + /* documentation. */ + /* */ +#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS + /*************************************************************************/ /* */ /* Alternate Glyph Image Format support */ diff --git a/config/unix/detect.mk b/config/unix/detect.mk index 72b3b86e5..2ce47e5e5 100644 --- a/config/unix/detect.mk +++ b/config/unix/detect.mk @@ -18,9 +18,13 @@ ifeq ($(PLATFORM),ansi) - has_inittab := $(strip $(wildcard /etc/inittab)) - ifneq ($(has_inittab),) +# Some Unix systems like *BSD do not have a /etc/inittab so we commented +# the line.. (thanks to Yamano-uchi, Hidetoshi for pointing this out).. +# +# has_inittab := $(strip $(wildcard /etc/inittab)) + has_init := $(strip $(wildcard /sbin/init)) + ifneq ($(has_init),) PLATFORM := unix COPY := cp diff --git a/demos/Makefile b/demos/Makefile index 4020c9398..5cac17dc3 100644 --- a/demos/Makefile +++ b/demos/Makefile @@ -152,7 +152,7 @@ else # # The list of demonstration programs to build. # - EXES := ftlint ftview fttimer + EXES := ftlint ftview fttimer compos ftstring ifneq ($(findstring $(PLATFORM),os2 unix),) EXES += ttdebug @@ -182,9 +182,15 @@ else $(OBJ_)ftlint.$O: $(SRC_DIR_)ftlint.c $(COMPILE) $T$@ $< + $(OBJ_)compos.$O: $(SRC_DIR_)compos.c + $(COMPILE) $T$@ $< + $(OBJ_)ftgrays.$O: $(SRC_DIR_)ftgrays.c $(COMPILE) $T$@ $< + $(OBJ_)ftgrays2.$O: $(SRC_DIR_)ftgrays2.c + $(COMPILE) $T$@ $< + $(OBJ_)fttry.$O: $(SRC_DIR_)fttry.c $(COMPILE) $T$@ $< @@ -192,9 +198,19 @@ else $(OBJ_)ftview.$O: $(SRC_DIR_)ftview.c $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + $(OBJ_)ftstring.$O: $(SRC_DIR_)ftstring.c $(GRAPH_LIB) + $(COMPILE) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + + $(OBJ_)try.$O: $(SRC_DIR_)try.c $(GRAPH_LIB) + $(COMPILE) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + $(OBJ_)fttimer.$O: $(SRC_DIR_)fttimer.c $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + $(OBJ_)fttimer2.$O: $(SRC_DIR_)fttimer2.c $(GRAPH_LIB) + $(COMPILE) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + + # $(OBJ_)ftsbit.$O: $(SRC_DIR)/ftsbit.c $(GRAPH_LIB) # $(COMPILE) $T$@ $< @@ -233,6 +249,9 @@ else $(BIN_)ftlint$E: $(OBJ_)ftlint.$O $(FTLIB) $(COMMON_OBJ) $(COMMON_LINK) + $(BIN_)compos$E: $(OBJ_)compos.$O $(FTLIB) $(COMMON_OBJ) + $(COMMON_LINK) + $(BIN_)fttry$E: $(OBJ_)fttry.$O $(FTLIB) $(LINK) @@ -249,9 +268,20 @@ else $(BIN_)ftview$E: $(OBJ_)ftview.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) $(OBJ_)ftgrays.$O $(GRAPH_LINK) $(OBJ_)ftgrays.$O + $(BIN_)ftstring$E: $(OBJ_)ftstring.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) $(OBJ_)ftgrays.$O + $(GRAPH_LINK) $(OBJ_)ftgrays.$O + + + $(BIN_)try$E: $(OBJ_)try.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) $(OBJ_)ftgrays2.$O + $(GRAPH_LINK) $(OBJ_)ftgrays2.$O + $(BIN_)fttimer$E: $(OBJ_)fttimer.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) $(OBJ_)ftgrays.$O $(GRAPH_LINK) $(OBJ_)ftgrays.$O + $(BIN_)fttimer2$E: $(OBJ_)fttimer2.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) $(OBJ_)ftgrays2.$O + $(GRAPH_LINK) $(OBJ_)ftgrays2.$O + + endif # EOF diff --git a/demos/src/ftgrays.c b/demos/src/ftgrays.c index a24196a86..be368534f 100644 --- a/demos/src/ftgrays.c +++ b/demos/src/ftgrays.c @@ -55,6 +55,11 @@ #define ErrRaster_Invalid_Outline -1 #include "ftgrays.h" +#ifdef _STANDALONE_ +#error "implementation of FT_Outline_Decompose missing !!!" +#else +#include /* to link to FT_Outline_Decompose */ +#endif #define xxxDEBUG_GRAYS @@ -91,6 +96,70 @@ #define UPSCALE(x) (PIXEL_BITS >= 6 ? (x) << (PIXEL_BITS-6) : (x) >> (6-PIXEL_BITS)) #define DOWNSCALE(x) (PIXEL_BITS >= 6 ? (x) >> (PIXEL_BITS-6) : (x) << (6-PIXEL_BITS)) + + + +/****************************************************************************/ +/* */ +/* TYPE DEFINITIONS */ +/* */ + +typedef int TScan; +typedef long TPos; +typedef float TDist; + +#define FT_MAX_GRAY_SPANS 32 + + +typedef struct TCell_ +{ + TScan x; + TScan y; + int area; + int cover; + +} TCell, *PCell; + + +typedef struct TRaster_ +{ + PCell cells; + int max_cells; + int num_cells; + + TScan min_ex, max_ex; + TScan min_ey, max_ey; + + int area; + int cover; + int invalid; + + TScan ex, ey; + TScan cx, cy; + TPos x, y; + + TScan last_ey; + + FT_Vector bez_stack[32*3]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + + FT_Span gray_spans[ FT_MAX_GRAY_SPANS ]; + int num_gray_spans; + + FT_Raster_Span_Func render_span; + void* render_span_data; + int span_y; + + void* memory; + +} TRaster, *PRaster; + + + + /****************************************************************************/ /* */ /* INITIALIZE THE CELLS TABLE */ @@ -783,399 +852,6 @@ int check_sort( PCell cells, int count ) #endif #endif -#if 0 - static - int FT_Decompose_Outline( FT_Outline* outline, - FT_Outline_Funcs* interface, - void* user ) - { - typedef enum _phases - { - phase_point, - phase_conic, - phase_cubic, - phase_cubic2 - - } TPhase; - - FT_Vector v_first; - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - - FT_Vector* point; - FT_Vector* limit; - char* tags; - - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - int error; - char tag; /* current point's state */ - - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - last = outline->contours[n]; - limit = outline->points + last; - - v_first = outline->points[first]; - v_last = outline->points[last]; - - v_start = v_control = v_first; - - 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 ) - goto Invalid_Outline; - - /* 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--; - } - - error = interface->move_to( &v_start, user ); - if (error) goto Exit; - - while (point < limit) - { - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - switch (tag) - { - case FT_Curve_Tag_On: /* emit a single line_to */ - { - error = interface->line_to( point, user ); - if (error) goto Exit; - continue; - } - - - case FT_Curve_Tag_Conic: /* consume conic arcs */ - { - v_control = point[0]; - - Do_Conic: - if (point < limit) - { - FT_Vector v_middle; - - point++; - tags++; - tag = FT_CURVE_TAG( tags[0] ); - - if (tag == FT_Curve_Tag_On) - { - error = interface->conic_to( &v_control, point, user ); - if (error) goto Exit; - continue; - } - - if (tag != FT_Curve_Tag_Conic) - goto Invalid_Outline; - - v_middle.x = (v_control.x + point->x)/2; - v_middle.y = (v_control.y + point->y)/2; - - error = interface->conic_to( &v_control, &v_middle, user ); - if (error) goto Exit; - - v_control = point[0]; - goto Do_Conic; - } - - error = interface->conic_to( &v_control, &v_start, user ); - goto Close; - } - - default: /* FT_Curve_Tag_Cubic */ - { - if ( point+1 > limit || - FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic ) - goto Invalid_Outline; - - point += 2; - tags += 2; - - if (point <= limit) - { - error = interface->cubic_to( point-2, point-1, point, user ); - if (error) goto Exit; - continue; - } - - error = interface->cubic_to( point-2, point-1, &v_start, user ); - goto Close; - } - } - } - - /* close the contour with a line segment */ - error = interface->line_to( &v_start, user ); - - Close: - if (error) goto Exit; - first = last+1; - } - - return 0; - Exit: - return error; - - Invalid_Outline: - return -1; - } -#else - static - int FT_Decompose_Outline( FT_Outline* outline, - FT_Outline_Funcs* interface, - void* user ) - { - typedef enum _phases - { - phase_point, - phase_conic, - phase_cubic, - phase_cubic2 - - } TPhase; - - FT_Vector v_first; - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_control2; - FT_Vector v_start; - - FT_Vector* point; - char* tags; - - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - int index; /* current point's index */ - - int error; - - char tag; /* current point's state */ - TPhase phase; - - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - - last = outline->contours[n]; - - v_first = outline->points[first]; - v_last = outline->points[last]; - - v_start = v_control = v_first; - - tag = FT_CURVE_TAG( outline->tags[first] ); - index = first; - - /* A contour cannot start with a cubic control point! */ - - if ( tag == FT_Curve_Tag_Cubic ) - return ErrRaster_Invalid_Outline; - - - /* 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; - } - 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; - } - phase = phase_conic; - } - else - phase = phase_point; - - - /* Begin a new contour with MOVE_TO */ - - error = interface->move_to( &v_start, user ); - if ( error ) - return error; - - point = outline->points + first; - tags = outline->tags + first; - - /* now process each contour point individually */ - - while ( index < last ) - { - index++; - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - - switch ( phase ) - { - case phase_point: /* the previous point was on the curve */ - - switch ( tag ) - { - /* two succesive on points -> emit segment */ - case FT_Curve_Tag_On: - error = interface->line_to( point, user ); - break; - - /* on point + conic control -> remember control point */ - case FT_Curve_Tag_Conic: - v_control = point[0]; - phase = phase_conic; - break; - - /* on point + cubic control -> remember first control */ - default: - v_control = point[0]; - phase = phase_cubic; - break; - } - break; - - case phase_conic: /* the previous point was a conic control */ - - switch ( tag ) - { - /* conic control + on point -> emit conic arc */ - case FT_Curve_Tag_On: - error = interface->conic_to( &v_control, point, user ); - phase = phase_point; - break; - - /* two successive conics -> emit conic arc `in between' */ - case FT_Curve_Tag_Conic: - { - FT_Vector v_middle; - - - v_middle.x = (v_control.x + point->x)/2; - v_middle.y = (v_control.y + point->y)/2; - - error = interface->conic_to( &v_control, - &v_middle, user ); - v_control = point[0]; - } - break; - - default: - error = ErrRaster_Invalid_Outline; - } - break; - - case phase_cubic: /* the previous point was a cubic control */ - - /* this point _must_ be a cubic control too */ - if ( tag != FT_Curve_Tag_Cubic ) - return ErrRaster_Invalid_Outline; - - v_control2 = point[0]; - phase = phase_cubic2; - break; - - - case phase_cubic2: /* the two previous points were cubics */ - - /* this point _must_ be an on point */ - if ( tag != FT_Curve_Tag_On ) - error = ErrRaster_Invalid_Outline; - else - error = interface->cubic_to( &v_control, &v_control2, - point, user ); - phase = phase_point; - break; - } - - /* lazy error testing */ - if ( error ) - return error; - } - - /* end of contour, close curve cleanly */ - error = 0; - - tag = FT_CURVE_TAG( outline->tags[first] ); - - switch ( phase ) - { - case phase_point: - if ( tag == FT_Curve_Tag_On ) - error = interface->line_to( &v_first, user ); - break; - - case phase_conic: - error = interface->conic_to( &v_control, &v_start, user ); - break; - - case phase_cubic2: - if ( tag == FT_Curve_Tag_On ) - error = interface->cubic_to( &v_control, &v_control2, - &v_first, user ); - else - error = ErrRaster_Invalid_Outline; - break; - - default: - error = ErrRaster_Invalid_Outline; - break; - } - - if ( error ) - return error; - - first = last + 1; - } - - return 0; - } - -#endif static int Move_To( FT_Vector* to, @@ -1224,7 +900,7 @@ int check_sort( PCell cells, int count ) static - void grays_render_span( int y, int count, FT_GraySpan* spans, PRaster raster ) + void grays_render_span( int y, int count, FT_Span* spans, PRaster raster ) { unsigned char *p, *q, *limit; FT_Bitmap* map = &raster->target; @@ -1270,21 +946,12 @@ int check_sort( PCell cells, int count ) } #endif -#if 0 - static - void grays_hline( RAS_ARG_ TScan x, TScan y, TPos area, int count ) - { - if (area) - fprintf( stderr, "hline( %3d, %3d, %2d, %5.2f )\n", - y, x, count, (float)area/(2.0*ONE_PIXEL*ONE_PIXEL) ); - } -#else static void grays_hline( RAS_ARG_ TScan x, TScan y, TPos area, int acount ) { - FT_GraySpan* span; - int count; - int coverage; + FT_Span* span; + int count; + int coverage; /* compute the coverage line's coverage, depending on the */ /* outline fill rule.. */ @@ -1331,7 +998,8 @@ int check_sort( PCell cells, int count ) if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS) { if (ras.render_span) - ras.render_span( ras.span_y, count, ras.gray_spans, ras.render_span_closure ); + ras.render_span( ras.span_y, count, ras.gray_spans, + ras.render_span_data ); /* ras.render_span( span->y, ras.gray_spans, count ); */ #ifdef DEBUG_GRAYS @@ -1341,7 +1009,8 @@ int check_sort( PCell cells, int count ) fprintf( stderr, "y=%3d ", ras.span_y ); span = ras.gray_spans; for (n = 0; n < count; n++, span++) - fprintf( stderr, "[%d..%d]:%02x ", span->x, span->x + span->len-1, span->coverage ); + fprintf( stderr, "[%d..%d]:%02x ", + span->x, span->x + span->len-1, span->coverage ); fprintf( stderr, "\n" ); } #endif @@ -1362,7 +1031,7 @@ int check_sort( PCell cells, int count ) ras.num_gray_spans++; } } -#endif + static void grays_sweep( RAS_ARG_ FT_Bitmap* target ) @@ -1427,7 +1096,7 @@ int check_sort( PCell cells, int count ) if (ras.render_span && ras.num_gray_spans > 0) ras.render_span( ras.span_y, ras.num_gray_spans, - ras.gray_spans, ras.render_span_closure ); + ras.gray_spans, ras.render_span_data ); #ifdef DEBUG_GRAYS { int n; @@ -1465,7 +1134,7 @@ int check_sort( PCell cells, int count ) ras.num_cells = 0; /* Now decompose curve */ - if ( FT_Decompose_Outline( outline, &interface, &ras ) ) + if ( FT_Outline_Decompose( outline, &interface, &ras ) ) return 1; /* XXX: the error condition is in ras.error */ @@ -1475,10 +1144,12 @@ int check_sort( PCell cells, int count ) extern - int grays_raster_render( TRaster* raster, - FT_Outline* outline, - FT_Bitmap* target_map ) + int grays_raster_render( PRaster raster, + FT_Raster_Params* params ) { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + if ( !raster || !raster->cells || !raster->max_cells ) return -1; @@ -1495,6 +1166,10 @@ int check_sort( PCell cells, int count ) if ( !target_map || !target_map->buffer ) return -1; + /* XXXX: this version does not support monochrome rendering yet ! */ + if ( !(params->flags & ft_raster_flag_aa) ) + return -1; + ras.outline = *outline; ras.target = *target_map; ras.num_cells = 0; @@ -1513,49 +1188,90 @@ int check_sort( PCell cells, int count ) check_sort( ras.cells, ras.num_cells ); dump_cells( RAS_VAR ); #endif - ras.render_span = (FT_GraySpan_Func)grays_render_span; - ras.render_span_closure = &ras; + + ras.render_span = (FT_Raster_Span_Func)grays_render_span; + ras.render_span_data = &ras; + if ( params->flags & ft_raster_flag_direct ) + { + ras.render_span = (FT_Raster_Span_Func)params->gray_spans; + ras.render_span_data = params->user; + } grays_sweep( (PRaster)raster, target_map ); return 0; } + /**** RASTER OBJECT CREATION : in standalone mode, we simply use *****/ + /**** a static object .. *****/ +#ifdef _STANDALONE_ - - - - extern - int grays_raster_init( FT_Raster raster, - const char* pool_base, - long pool_size ) + static + int grays_raster_new( void* memory, FT_Raster *araster ) { -/* static const char default_palette[5] = { 0, 1, 2, 3, 4 }; */ + static FT_RasterRec_ the_raster; + *araster = &the_raster; + memset( &the_raster, sizeof(the_raster), 0 ); + return 0; + } - /* check the object address */ - if ( !raster ) - return -1; + static + void grays_raster_done( FT_Raster raster ) + { + /* nothing */ + (void)raster; + } - /* check the render pool - we won't go under 4 Kb */ - if ( !pool_base || pool_size < 4096 ) - return -1; +#else - /* save the pool */ - init_cells( (PRaster)raster, (char*)pool_base, pool_size ); +#include "ftobjs.h" - return 0; + static + int grays_raster_new( FT_Memory memory, FT_Raster* araster ) + { + FT_Error error; + PRaster raster; + + *araster = 0; + if ( !ALLOC( raster, sizeof(TRaster) )) + { + raster->memory = memory; + *araster = (FT_Raster)raster; + } + + return error; + } + + static + void grays_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + FREE( raster ); + } + +#endif + + + + + static + void grays_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + if (raster && pool_base && pool_size >= 4096) + init_cells( (PRaster)raster, (char*)pool_base, pool_size ); } - - FT_Raster_Interface ft_grays_raster = + FT_Raster_Funcs ft_grays_raster = { - sizeof( TRaster ), ft_glyph_format_outline, - - (FT_Raster_Init_Proc) grays_raster_init, - (FT_Raster_Set_Mode_Proc) 0, - (FT_Raster_Render_Proc) grays_raster_render + + (FT_Raster_New_Func) grays_raster_new, + (FT_Raster_Reset_Func) grays_raster_reset, + (FT_Raster_Set_Mode_Func) 0, + (FT_Raster_Render_Func) grays_raster_render, + (FT_Raster_Done_Func) grays_raster_done }; - diff --git a/demos/src/ftgrays.h b/demos/src/ftgrays.h index 5e9eb00b7..b9c8dc36c 100644 --- a/demos/src/ftgrays.h +++ b/demos/src/ftgrays.h @@ -1,78 +1,7 @@ #ifndef FTGRAYS_H #define FTGRAYS_H -typedef int TScan; -typedef long TPos; -typedef float TDist; -#define FT_MAX_GRAY_SPANS 32 - -typedef struct FT_GraySpan_ -{ - short x; - short len; - unsigned char coverage; - -} FT_GraySpan; - -typedef int (*FT_GraySpan_Func)( int y, - int count, - FT_GraySpan* spans, - void* user ); - - -typedef struct TCell_ -{ - TScan x; - TScan y; - int area; - int cover; - -} TCell, *PCell; - - -typedef struct TRaster_ -{ - PCell cells; - int max_cells; - int num_cells; - - TScan min_ex, max_ex; - TScan min_ey, max_ey; - - int area; - int cover; - int invalid; - - TScan ex, ey; - TScan cx, cy; - TPos x, y; - - TScan last_ey; - - FT_Vector bez_stack[32*3]; - int lev_stack[32]; - - FT_Outline outline; - FT_Bitmap target; - - FT_GraySpan gray_spans[ FT_MAX_GRAY_SPANS ]; - int num_gray_spans; - - FT_GraySpan_Func render_span; - void* render_span_closure; - int span_y; - -} TRaster, *PRaster; - - extern - int grays_raster_render( TRaster* raster, - FT_Outline* outline, - FT_Bitmap* target_map ); - - extern - int grays_raster_init( FT_Raster raster, - const char* pool_base, - long pool_size ); + extern FT_Raster_Funcs ft_grays_raster; #endif diff --git a/demos/src/ftgrays2.c b/demos/src/ftgrays2.c index 073e65770..80aba2ac6 100644 --- a/demos/src/ftgrays2.c +++ b/demos/src/ftgrays2.c @@ -8,7 +8,7 @@ /* */ /* After writing a "perfect" anti-aliaser (see ftgrays.c), it is clear */ /* that the standard FreeType renderer is better at generating glyph images */ -/* because it uses an approximation that simply produced more contrasted */ +/* because it uses an approximation that simply produces more contrasted */ /* edges, making its output more legible.. */ /* */ /* This code is an attempt to rewrite the standard renderer in order to */ @@ -19,14 +19,22 @@ /* of span in successive scan-lines (the standard code is forced to use */ /* an intermediate buffer, and this is just _bad_ :-) */ /* */ +/* */ +/* This thing works, but it's slower than the original ftraster.c, */ +/* probably because the bezier intersection code is different.. */ +/* */ +/* Note that Type 1 fonts, using a reverse fill algorithm are not */ +/* supported for now (this should come soon though..) */ +/* */ #include #define _STANDALONE_ -#define xxxDEBUG_GRAYS -#define SPECIAL -#define HORZ +#define DEBUG_GRAYS +#define DIRECT_BEZIER +#define PRECISION_STEP ONE_HALF +#define xxxDYNAMIC_BEZIER_STEPS #define ErrRaster_Invalid_Outline -1 #define ErrRaster_Overflow -2 @@ -42,6 +50,99 @@ #include #endif +typedef int TScan; +typedef long TPos; +typedef float TDist; + +#define FT_MAX_GRAY_SPANS 32 + +typedef struct FT_GraySpan_ +{ + short x; + short len; + unsigned char coverage; + +} FT_GraySpan; + +typedef int (*FT_GraySpan_Func)( int y, + int count, + FT_GraySpan* spans, + void* user ); + +typedef enum { + + dir_up = 0, + dir_down = 1, + dir_right = 2, + dir_left = 3, + + dir_horizontal = 2, + dir_reverse = 1, + dir_silent = 4, + + dir_unknown = 8 + +} TDir; + + +typedef struct TCell_ +{ + unsigned short x; + unsigned short y; + unsigned short pos; + TDir dir; + +} TCell, *PCell; + + + +typedef struct TRaster_ +{ + PCell cells; + PCell cursor; + PCell cell_limit; + int max_cells; + int num_cells; + + TScan min_ex, max_ex; + TScan min_ey, max_ey; + TPos min_x, min_y; + TPos max_x, max_y; + + TScan ex, ey; + TScan cx, cy; + TPos x, y; + + PCell contour_cell; /* first contour cell */ + + char joint; + char horizontal; + TDir dir; + PCell last; + + FT_Vector starter; + FT_Vector* start; + + int error; + + FT_Vector* arc; + FT_Vector bez_stack[32*3]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + + FT_GraySpan gray_spans[ FT_MAX_GRAY_SPANS ]; + int num_gray_spans; + + FT_GraySpan_Func render_span; + void* render_span_closure; + int span_y; + +} TRaster, *PRaster; + + + #ifndef FT_STATIC_RASTER #define RAS_ARG PRaster raster @@ -122,8 +223,8 @@ int write_cell( RAS_ARG_ PCell cell, TPos u, TPos v, TDir dir ) /* get rid of horizontal cells with pos == 0, they're irrelevant */ if ( FRAC(u) == 0 ) goto Nope; - cell->y = TRUNC( u - ras.min_y ); - cell->x = TRUNC( v - ras.min_x ); + cell->y = (unsigned short)TRUNC( u - ras.min_y ); + cell->x = (unsigned short)TRUNC( v - ras.min_x ); } else { @@ -137,8 +238,8 @@ int write_cell( RAS_ARG_ PCell cell, TPos u, TPos v, TDir dir ) /* all cells that are on the left of the clipping box are located */ /* on the same virtual "border" cell.. */ if (u < 0) u = -1; - cell->x = TRUNC( u ); - cell->y = TRUNC( v ); + cell->x = (unsigned short)TRUNC( u ); + cell->y = (unsigned short)TRUNC( v ); } cell->dir = dir; cell->pos = FRAC(u); @@ -257,6 +358,10 @@ Exit: du = u2 - u1; dv = v2 - v1; + /* set the silent flag */ + if (du > dv) + dir |= dir_silent; + /* compute the first scanline in "e1" */ e1 = CEILING(v1); if (e1 == v1 && ras.joint) @@ -423,6 +528,35 @@ void split_conic( FT_Vector* base ) } +static +void split_cubic( FT_Vector* base ) +{ + TPos a, b, c, d; + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c ) / 2; + base[5].x = b = ( base[3].x + d ) / 2; + c = ( c + d ) / 2; + base[2].x = a = ( a + c ) / 2; + base[4].x = b = ( b + c ) / 2; + base[3].x = ( a + b ) / 2; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c ) / 2; + base[5].y = b = ( base[3].y + d ) / 2; + c = ( c + d ) / 2; + base[2].y = a = ( a + c ) / 2; + base[4].y = b = ( b + c ) / 2; + base[3].y = ( a + b ) / 2; +} + + + +#ifndef DIRECT_BEZIER static int render_conic( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2 ) { @@ -483,32 +617,6 @@ int render_conic( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2 ) } -static -void split_cubic( FT_Vector* base ) -{ - TPos a, b, c, d; - - base[6].x = base[3].x; - c = base[1].x; - d = base[2].x; - base[1].x = a = ( base[0].x + c ) / 2; - base[5].x = b = ( base[3].x + d ) / 2; - c = ( c + d ) / 2; - base[2].x = a = ( a + c ) / 2; - base[4].x = b = ( b + c ) / 2; - base[3].x = ( a + b ) / 2; - - base[6].y = base[3].y; - c = base[1].y; - d = base[2].y; - base[1].y = a = ( base[0].y + c ) / 2; - base[5].y = b = ( base[3].y + d ) / 2; - c = ( c + d ) / 2; - base[2].y = a = ( a + c ) / 2; - base[4].y = b = ( b + c ) / 2; - base[3].y = ( a + b ) / 2; -} - static int render_cubic( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2, @@ -581,6 +689,390 @@ int render_cubic( RAS_ARG_ TPos x1, TPos y1, } } } +#else /* !DIRECT_BEZIER */ + /* A function type describing the functions used to split bezier arcs */ + typedef void (*TSplitter)( FT_Vector* base ); + +#ifdef DYNAMIC_BEZIER_STEPS + static + TPos Dynamic_Bezier_Threshold( RAS_ARG_ int degree, FT_Vector* arc ) + { + TPos min_x, max_x, min_y, max_y, A, B; + TPos wide_x, wide_y, threshold; + + FT_Vector* cur = arc; + FT_Vector* limit = cur + degree; + + /* first of all, set the threshold to the maximum x or y extent */ + min_x = max_x = arc[0].x; + min_y = max_y = arc[0].y; + cur++; + for ( ; cur < limit; cur++ ) + { + TPos x = cur->x; + TPos y = cur->y; + + if ( x < min_x ) min_x = x; + if ( x > max_x ) max_x = x; + + if ( y < min_y ) min_y = y; + if ( y > max_y ) max_y = y; + } + wide_x = (max_x - min_x) << 4; + wide_y = (max_y - min_y) << 4; + + threshold = wide_x; + if (threshold < wide_y) threshold = wide_y; + + /* now compute the second and third order error values */ + + wide_x = arc[0].x + arc[1].x - arc[2].x*2; + wide_y = arc[0].y + arc[1].y - arc[2].y*2; + + if (wide_x < 0) wide_x = -wide_x; + if (wide_y < 0) wide_y = -wide_y; + + A = wide_x; if ( A < wide_y ) A = wide_y; + + if (degree >= 3) + { + wide_x = arc[3].x - arc[0].x + 3*(arc[2].x - arc[3].x); + wide_y = arc[3].y - arc[0].y + 3*(arc[2].y - arc[3].y); + + if (wide_x < 0) wide_x = -wide_x; + if (wide_y < 0) wide_y = -wide_y; + + B = wide_x; if ( B < wide_y ) B = wide_y; + } + else + B = 0; + + while ( A > 0 || B > 0 ) + { + threshold >>= 1; + A >>= 2; + B >>= 3; + } + + if (threshold < PRECISION_STEP) + threshold = PRECISION_STEP; + + return threshold; + } +#endif /* DYNAMIC_BEZIER_STEPS */ + + static + int render_bezier( RAS_ARG_ int degree, + TSplitter splitter, + TPos minv, + TPos maxv, + TDir dir ) + { + TPos v1, v2, u, v, e1, e2, threshold; + int reverse; + + FT_Vector* arc; + FT_Vector init; + + PCell top; + + arc = ras.arc; + init = arc[0]; + + arc[0].y -= ONE_HALF; + arc[1].y -= ONE_HALF; + arc[2].y -= ONE_HALF; + maxv -= ONE_PIXEL; + + top = ras.cursor; + + /* ensure that our segment is ascending */ + v1 = arc[degree].y; + v2 = arc[0].y; + reverse = 0; + if ( v2 < v1 ) + { + TPos tmp; + v1 = -v1; + v2 = -v2; + arc[0].y = v2; + arc[1].y = -arc[1].y; + arc[degree].y = v1; + if (degree > 2) + arc[2].y = -arc[2].y; + + tmp = minv; minv = -maxv; maxv = -tmp; + reverse = 1; + } + + if ( v2 < minv || v1 > maxv ) + goto Fin; + + /* compute the first scanline in "e1" */ + e1 = CEILING(v1); + if (e1 == v1 && ras.joint) + e1 += ONE_PIXEL; + + /* compute the last scanline in "e2" */ + if (v2 <= maxv) + { + e2 = FLOOR(v2); + ras.joint = (v2 == e2); + } + else + { + e2 = maxv; + ras.joint = 0; + } + + /* exit if the current scanline is already above the max scanline */ + if ( e2 < e1 ) + goto Fin; + + /* check for overflow */ + if ( ( top + TRUNC(e2-e1)+1 ) >= ras.cell_limit ) + { + ras.cursor = top; + ras.error = ErrRaster_Overflow; + return 1; + } + +#ifdef DYNAMIC_BEZIER_STEPS + /* compute dynamic bezier step threshold */ + threshold = Dynamic_Bezier_Threshold( RAS_VAR_ degree, arc ); +#else + threshold = PRECISION_STEP; +#endif + + /* loop while there is still an arc on the bezier stack */ + /* and the current scan line is below y max == e2 */ + while ( arc >= ras.arc && e1 <= e2 ) + { + ras.joint = 0; + + v2 = arc[0].y; /* final y of the top-most arc */ + + if ( v2 > e1 ) /* the arc intercepts the current scanline */ + { + v1 = arc[degree].y; /* start y of top-most arc */ + + if ( v2 >= e1 + ONE_PIXEL || v2 - v1 >= threshold ) + { + /* if the arc's height is too great, split it */ + splitter( arc ); + arc += degree; + } + else + { + /* otherwise, approximate it as a segment and compute */ + /* its intersection with the current scanline */ + u = arc[degree].x + + FMulDiv( arc[0].x-arc[degree].x, + e1 - v1, + v2 - v1 ); + + v = e1; if (reverse) v = -e1; + v += ONE_HALF; + if (WRITE_CELL( top, u, v, dir )) + top++; + + arc -= degree; /* pop the arc */ + e1 += ONE_PIXEL; /* go to next scanline */ + } + } + else + { + if ( v2 == e1 ) /* if the arc falls on the scanline */ + { /* record its _joint_ intersection */ + ras.joint = 1; + u = arc[degree].x; + v = e1; if (reverse) v = -e1; + v += ONE_HALF; + if (WRITE_CELL( top, u, v, dir )) + top++; + + e1 += ONE_PIXEL; /* go to next scanline */ + } + arc -= degree; /* pop the arc */ + } + } + + Fin: + ras.arc[0] = init; + ras.cursor = top; + return 0; + } + + +static +int render_conic( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2 ) +{ + TPos x0, y0; + TPos minv, maxv; + FT_Vector* arc; + + x0 = ras.x; + y0 = ras.y; + + minv = ras.min_y; + maxv = ras.max_y; + if (ras.horizontal) + { + minv = ras.min_x; + maxv = ras.max_x; + } + + arc = ras.bez_stack; + arc[2].x = ras.x; arc[2].y = ras.y; + arc[1].x = x1; arc[1].y = y1; + arc[0].x = x2; arc[0].y = y2; + + do + { + TDir dir; + TPos ymin, ymax; + + y0 = arc[2].y; + y1 = arc[1].y; + y2 = arc[0].y; + x2 = arc[0].x; + + /* first, categorize the Bezier arc */ + ymin = y0; + ymax = y2; + if (ymin > ymax) + { + ymin = y2; + ymax = y0; + } + + if (y1 < ymin || y1 > ymax) + { + /* this arc isn't y-monotonous, split it */ + split_conic( arc ); + arc += 2; + } + else if ( y0 == y2 ) + { + /* this arc is flat, ignore it */ + arc -= 2; + } + else + { + /* the arc is y-monotonous, either ascending or descending */ + /* detect a change of direction */ + dir = ( y0 < y2 ) ? dir_up : dir_down; + if (ras.horizontal) dir |= dir_horizontal; + if (dir != ras.dir) + { + ras.joint = 0; + ras.dir = dir; + } + + ras.arc = arc; + if (render_bezier( RAS_VAR_ 2, split_conic, minv, maxv, dir )) + goto Fail; + arc -= 2; + } + } while ( arc >= ras.bez_stack ); + + ras.x = x2; + ras.y = y2; + return 0; +Fail: + return 1; +} + +static +int render_cubic( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2, TPos x3, TPos y3 ) +{ + TPos x0, y0; + TPos minv, maxv; + FT_Vector* arc; + + x0 = ras.x; + y0 = ras.y; + + minv = ras.min_y; + maxv = ras.max_y; + if (ras.horizontal) + { + minv = ras.min_x; + maxv = ras.max_x; + } + + arc = ras.bez_stack; + arc[0].x = ras.x; arc[0].y = ras.y; + arc[1].x = x1; arc[1].y = y1; + arc[2].x = x2; arc[2].y = y2; + arc[3].x = x3; arc[3].y = y3; + + do + { + TDir dir; + TPos ymin1, ymax1, ymin2, ymax2; + + y0 = arc[3].y; + y1 = arc[2].y; + y2 = arc[1].y; + y3 = arc[0].y; + x3 = arc[0].x; + + /* first, categorize the Bezier arc */ + ymin1 = y0; + ymax1 = y3; + if (ymin1 > ymax1) + { + ymin1 = y3; + ymax1 = y0; + } + + ymin2 = y1; + ymax2 = y2; + if (ymin2 > ymax2) + { + ymin2 = y2; + ymax2 = y1; + } + + if ( ymin2 < ymin1 || ymax2 > ymax1) + { + /* this arc isn't y-monotonous, split it */ + split_cubic( arc ); + arc += 3; + } + else if ( y0 == y3 ) + { + /* this arc is flat, ignore it */ + arc -= 3; + } + else + { + /* the arc is y-monotonous, either ascending or descending */ + /* detect a change of direction */ + dir = ( y0 < y3 ) ? dir_up : dir_down; + if (ras.horizontal) dir |= dir_horizontal; + if (dir != ras.dir) + { + ras.joint = 0; + ras.dir = dir; + } + + ras.arc = arc; + if (render_bezier( RAS_VAR_ 3, split_cubic, minv, maxv, dir )) + goto Fail; + arc -= 3; + } + } while ( arc >= ras.bez_stack ); + + ras.x = x2; + ras.y = y2; + return 0; +Fail: + return 1; +} + +#endif /* !DIRECT_BEZIER */ static @@ -592,8 +1084,8 @@ int is_less_than( PCell a, PCell b ) if (a->x < b->x) goto Yes; if (a->x == b->x) { - TDir ad = a->dir & dir_horizontal; - TDir bd = b->dir & dir_horizontal; + TDir ad = a->dir & (dir_horizontal|dir_silent); + TDir bd = b->dir & (dir_horizontal|dir_silent); if ( ad < bd ) goto Yes; if ( ad == bd && a->pos < b->pos) goto Yes; } @@ -1308,7 +1800,7 @@ int check_sort( PCell cells, int count ) q = p + spans->x; limit = q + spans->len; for ( ; q < limit; q++ ) - q[0] = (spans->coverage+1) >> 1; + q[0] = spans->coverage >> 1; } } } @@ -1364,6 +1856,8 @@ int check_sort( PCell cells, int count ) if (coverage) { + x += ras.min_ex; + /* see if we can add this span to the current list */ count = ras.num_gray_spans; span = ras.gray_spans + count-1; @@ -1377,7 +1871,7 @@ int check_sort( PCell cells, int count ) if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS) { if (ras.render_span) - ras.render_span( ras.span_y, count, ras.gray_spans, ras.render_span_closure ); + ras.render_span( ras.min_ey + ras.span_y, count, ras.gray_spans, ras.render_span_closure ); /* ras.render_span( span->y, ras.gray_spans, count ); */ #ifdef DEBUG_GRAYS @@ -1452,32 +1946,41 @@ int check_sort( PCell cells, int count ) /* accumulate all start cells */ for (;;) { - /* XXX : for now, only deal with vertical intersections */ - switch ((cur->dir)&3) +#if 0 + /* we ignore silent cells for now XXXX */ + if (!(cur->dir & dir_silent)) +#endif { - case dir_up: - varea += ONE_PIXEL - cur->pos; - if (cur->pos <= 32) - hpos = ONE_PIXEL; - cover++; - numv++; - break; - - case dir_down: - varea -= ONE_PIXEL - cur->pos; - if (cur->pos <= 32) - hpos = 0; - cover--; - numv++; - break; + switch ((cur->dir)&3) + { + case dir_up: + varea += ONE_PIXEL - cur->pos; + if (cur->pos <= 32) + hpos = ONE_PIXEL; + cover++; + numv++; + break; - case dir_left: - harea += ONE_PIXEL - cur->pos; - break; - - default: - harea -= ONE_PIXEL - cur->pos; - break; + case dir_down: + varea -= ONE_PIXEL - cur->pos; + if (cur->pos <= 32) + hpos = 0; + cover--; + numv++; + break; +#if 0 + case dir_left: + harea += ONE_PIXEL - cur->pos; + break; + + default: + harea -= ONE_PIXEL - cur->pos; + break; +#else + default: + ; +#endif + } } ++cur; @@ -1489,15 +1992,14 @@ int check_sort( PCell cells, int count ) if (varea < 0) varea += ONE_PIXEL; if (harea < 0) harea += ONE_PIXEL; - if (harea) - area = varea + harea; - else + if (varea == 0) + area = 2*harea; + + else if (harea == 0) area = 2*varea; - -#if 1 - if ( varea < ONE_PIXEL && harea == 0 && (icover|cover) == 0 && area < ONE_PIXEL) - area += ONE_HALF; -#endif + + else + area = (varea+harea+ONE_PIXEL) >> 1; is_black = ( area >= 2*ONE_PIXEL ); @@ -1604,19 +2106,27 @@ int check_sort( PCell cells, int count ) /* compute vertical intersections */ if (FT_Outline_Decompose( outline, &interface, &ras )) return 1; -#if 1 +#if 0 /* compute horizontal intersections */ ras.horizontal = 1; return FT_Outline_Decompose( outline, &interface, &ras ); +#else + return 0; #endif } + + + + extern - int grays2_raster_render( TRaster* raster, - FT_Outline* outline, - FT_Bitmap* target_map ) + int grays2_raster_render( PRaster raster, + FT_Raster_Params* params ) { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + if ( !raster || !raster->cells || !raster->max_cells ) return -1; @@ -1665,41 +2175,76 @@ int check_sort( PCell cells, int count ) } + /**** RASTER OBJECT CREATION : in standalone mode, we simply use *****/ + /**** a static object .. *****/ +#ifdef _STANDALONE_ + + static + int grays2_raster_new( void* memory, FT_Raster *araster ) + { + static TRaster the_raster; + *araster = (FT_Raster)&the_raster; + memset( &the_raster, sizeof(the_raster), 0 ); + return 0; + } + + static + void grays2_raster_done( FT_Raster raster ) + { + /* nothing */ + (void)raster; + } + +#else + +#include "ftobjs.h" + + static + int grays2_raster_new( FT_Memory memory, FT_Raster* araster ) + { + FT_Error error; + PRaster raster; + + *araster = 0; + if ( !ALLOC( raster, sizeof(TRaster) )) + { + raster->memory = memory; + *araster = (FT_Raster)raster; + } + + return error; + } + + static + void grays2_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + FREE( raster ); + } + +#endif - extern - int grays2_raster_init( FT_Raster raster, + static + void grays2_raster_reset( FT_Raster raster, const char* pool_base, long pool_size ) { -/* static const char default_palette[5] = { 0, 1, 2, 3, 4 }; */ - - /* check the object address */ - if ( !raster ) - return -1; - - /* check the render pool - we won't go under 4 Kb */ - if ( !pool_base || pool_size < 4096 ) - return -1; - - /* save the pool */ - init_cells( (PRaster)raster, (char*)pool_base, pool_size ); - - return 0; + if (raster && pool_base && pool_size >= 4096) + init_cells( (PRaster)raster, (char*)pool_base, pool_size ); } - - FT_Raster_Interface ft_grays2_raster = + FT_Raster_Funcs ft_grays2_raster = { - sizeof( TRaster ), ft_glyph_format_outline, - - (FT_Raster_Init_Proc) grays2_raster_init, - (FT_Raster_Set_Mode_Proc) 0, - (FT_Raster_Render_Proc) grays2_raster_render + + (FT_Raster_New_Func) grays2_raster_new, + (FT_Raster_Reset_Func) grays2_raster_reset, + (FT_Raster_Set_Mode_Func) 0, + (FT_Raster_Render_Func) grays2_raster_render, + (FT_Raster_Done_Func) grays2_raster_done }; - diff --git a/demos/src/ftgrays2.h b/demos/src/ftgrays2.h index e127a8ed7..cba7bbe66 100644 --- a/demos/src/ftgrays2.h +++ b/demos/src/ftgrays2.h @@ -1,102 +1,9 @@ #ifndef FTGRAYS2_H #define FTGRAYS2_H -typedef int TScan; -typedef long TPos; -typedef float TDist; - -#define FT_MAX_GRAY_SPANS 32 - -typedef struct FT_GraySpan_ -{ - short x; - short len; - unsigned char coverage; - -} FT_GraySpan; - -typedef int (*FT_GraySpan_Func)( int y, - int count, - FT_GraySpan* spans, - void* user ); - -typedef enum { - - dir_up = 0, - dir_down = 1, - dir_right = 2, - dir_left = 3, - - dir_horizontal = 2, - dir_reverse = 1, - - dir_unknown = 4 - -} TDir; - -typedef struct TCell_ -{ - unsigned short x; - unsigned short y; - unsigned short pos; - TDir dir; - -} TCell, *PCell; - - - -typedef struct TRaster_ -{ - PCell cells; - PCell cursor; - PCell cell_limit; - int max_cells; - int num_cells; - - TScan min_ex, max_ex; - TScan min_ey, max_ey; - TPos min_x, min_y; - TPos max_x, max_y; - - TScan ex, ey; - TScan cx, cy; - TPos x, y; - - PCell contour_cell; /* first contour cell */ - - char joint; - char horizontal; - TDir dir; - PCell last; - - FT_Vector starter; - FT_Vector* start; - - int error; - - FT_Vector bez_stack[32*3]; - int lev_stack[32]; - - FT_Outline outline; - FT_Bitmap target; - - FT_GraySpan gray_spans[ FT_MAX_GRAY_SPANS ]; - int num_gray_spans; - - FT_GraySpan_Func render_span; - void* render_span_closure; - int span_y; - -} TRaster, *PRaster; +#include extern - int grays2_raster_render( TRaster* raster, - FT_Outline* outline, - FT_Bitmap* target_map ); - - extern - int grays2_raster_init( FT_Raster raster, - const char* pool_base, - long pool_size ); + FT_Raster_Funcs ft_grays2_raster; #endif diff --git a/demos/src/fttimer.c b/demos/src/fttimer.c index 295b67517..3be261513 100644 --- a/demos/src/fttimer.c +++ b/demos/src/fttimer.c @@ -78,10 +78,9 @@ int vio_Height, vio_Width; short visual; /* display glyphs while rendering */ - short gray_render; /* smooth fonts with gray levels */ + short antialias; /* smooth fonts with gray levels */ short force_low; - TRaster raster; #define RASTER_BUFF_SIZE 128000 char raster_buff[ RASTER_BUFF_SIZE ]; @@ -122,7 +121,7 @@ Bit.width = bit.width; Bit.pitch = bit.pitch; Bit.buffer = bit.buffer; - Bit.pixel_mode = gray_render ? ft_pixel_mode_grays : ft_pixel_mode_mono; + Bit.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono; Bit.num_grays = bit.grays; Clear_Buffer(); } @@ -219,10 +218,7 @@ FT_Error ConvertRaster( int index ) { outlines[index].flags |= ~ft_outline_single_pass; - if (use_grays) - return grays_raster_render( &raster, &outlines[index], &Bit ); - else - return FT_Outline_Get_Bitmap( library, &outlines[index], &Bit ); + return FT_Outline_Get_Bitmap( library, &outlines[index], &Bit ); } @@ -255,7 +251,7 @@ execname = argv[0]; - gray_render = 0; + antialias = 0; visual = 0; force_low = 0; @@ -264,7 +260,7 @@ switch ( argv[1][1] ) { case 'g': - gray_render = 1; + antialias = 1; break; case 'a': @@ -333,8 +329,12 @@ if ( (error = FT_Init_FreeType( &library )) ) Panic( "Error while initializing engine" ); - error = grays_raster_init( (FT_Raster)&raster, (const char*)raster_buff, RASTER_BUFF_SIZE ); - if (error) Panic( "Could not initialize smooth anti-aliasing renderer" ); + /* set-up smooth anti-aliaser */ + if (use_grays) + { + error = FT_Set_Raster( library, &ft_grays_raster ); + if (error) Panic( "Could not initialize smooth anti-aliasing renderer" ); + } /* Load face */ @@ -358,7 +358,7 @@ error = FT_Set_Pixel_Sizes( face, pixel_size, pixel_size ); if ( error ) Panic( "Could not reset instance" ); - bit.mode = gray_render ? gr_pixel_mode_gray : gr_pixel_mode_mono; + bit.mode = antialias ? gr_pixel_mode_gray : gr_pixel_mode_mono; bit.width = 640; bit.rows = 480; bit.grays = 128; diff --git a/demos/src/ftview.c b/demos/src/ftview.c index f125c8e2e..cc599a76d 100644 --- a/demos/src/ftview.c +++ b/demos/src/ftview.c @@ -59,7 +59,7 @@ $\243^\250*\265\371%!\247:/;.,?<>"; int ptsize; /* current point size */ int hinted = 1; /* is glyph hinting active ? */ - int gray_render = 1; /* is anti-aliasing active ? */ + int antialias = 1; /* is anti-aliasing active ? */ int use_sbits = 1; /* do we use embedded bitmaps ? */ int low_prec = 1; /* force low precision */ int Num; /* current first glyph index */ @@ -76,8 +76,9 @@ $\243^\250*\265\371%!\247:/;.,?<>"; int render_mode = 1; int use_grays = 0; - TRaster raster; - + /* the standard raster's interface */ + FT_Raster_Funcs std_raster; + #define RASTER_BUFF_SIZE 32768 char raster_buff[ RASTER_BUFF_SIZE ]; @@ -167,7 +168,7 @@ $\243^\250*\265\371%!\247:/;.,?<>"; if ( glyph->format == ft_glyph_format_outline ) { - pitch = ( gray_render ? (width+3) & -4 : (width+7) >> 3 ); + pitch = ( antialias ? (width+3) & -4 : (width+7) >> 3 ); size = pitch*height; if (size > MAX_BUFFER) @@ -176,13 +177,13 @@ $\243^\250*\265\371%!\247:/;.,?<>"; bit2.width = width; bit2.rows = height; bit2.pitch = pitch; - bit2.pixel_mode = gray_render ? ft_pixel_mode_grays : ft_pixel_mode_mono; + bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono; bit2.buffer = bit_buffer; bit3.rows = bit2.rows; bit3.width = bit2.width; bit3.pitch = bit2.pitch; - bit3.mode = gray_render ? bit.mode : gr_pixel_mode_mono; + bit3.mode = antialias ? bit.mode : gr_pixel_mode_mono; bit3.buffer = bit_buffer; bit3.grays = 128; @@ -192,10 +193,7 @@ $\243^\250*\265\371%!\247:/;.,?<>"; if (low_prec) glyph->outline.flags &= ~ft_outline_high_precision; - if (use_grays & gray_render) - error = grays_raster_render( &raster, &glyph->outline, &bit2 ); - else - error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 ); + error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 ); } else { @@ -416,6 +414,17 @@ $\243^\250*\265\371%!\247:/;.,?<>"; grListenSurface( surface, gr_event_key, &dummy_event ); } + static void reset_raster( void ) + { + FT_Error error; + + error = 1; + if ( use_grays && antialias ) + error = FT_Set_Raster( library, &ft_grays_raster ); + + if (error) + (void)FT_Set_Raster( library, &std_raster ); + } static int Process_Event( grEvent* event ) @@ -429,10 +438,11 @@ $\243^\250*\265\371%!\247:/;.,?<>"; return 0; case grKEY('a'): - gray_render = !gray_render; - new_header = ( gray_render + antialias = !antialias; + new_header = ( antialias ? "anti-aliasing is now on" : "anti-aliasing is now off" ); + reset_raster(); return 1; case grKEY('b'): @@ -451,6 +461,7 @@ $\243^\250*\265\371%!\247:/;.,?<>"; new_header = ( use_grays ? "now using the smooth anti-aliaser" : "now using the standard anti-aliaser" ); + reset_raster(); break; case grKEY('l'): @@ -598,10 +609,9 @@ $\243^\250*\265\371%!\247:/;.,?<>"; error = FT_Init_FreeType( &library ); if (error) PanicZ( "Could not initialise FreeType library" ); - error = grays_raster_init( (FT_Raster)&raster, (const char*)raster_buff, RASTER_BUFF_SIZE ); - if (error) PanicZ( "Could not initialize anti-aliasing renderer" ); + /* retrieve the standard raster's interface */ + (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster ); -/* FT_Set_Raster_Palette( library, 17, palette_17 ); */ NewFile: ptsize = orig_ptsize; diff --git a/include/freetype.h b/include/freetype.h index 489758827..3f6ba98c3 100644 --- a/include/freetype.h +++ b/include/freetype.h @@ -736,15 +736,6 @@ /* resolution and point-size independent data found in a font file. */ /* */ /* */ - /* driver :: A handle to the face's parent driver */ - /* object. */ - /* */ - /* memory :: A handle to the face's parent memory */ - /* object. Used for the allocation of */ - /* subsequent objects. */ - /* */ - /* stream :: A handle to the face's stream. */ - /* */ /* num_faces :: In the case where the face is located in a */ /* collection (i.e., a resource which embeds */ /* several faces), this is the total number of */ @@ -756,18 +747,6 @@ /* collections (which embed several fonts in a */ /* single resource/file). */ /* */ - /* generic :: A field reserved for client uses. See the */ - /* FT_Generic type description. */ - /* */ - /* glyph :: The face's associated glyph slot(s). This */ - /* object is created automatically with a new */ - /* face object. However, certain kinds of */ - /* applications (mainly tools like converters) */ - /* can need more than one slot to ease their */ - /* task. */ - /* */ - /* sizes_list :: The list of child sizes for this face. */ - /* */ /* face_flags :: A set of bit flags that give important */ /* information about the face; see the */ /* FT_FACE_FLAG_XXX macros for details. */ @@ -778,9 +757,6 @@ /* */ /* num_glyphs :: The total number of glyphs in the face. */ /* */ - /* num_charmaps :: The total number of character maps in the */ - /* face. */ - /* */ /* family_name :: The face's family name. This is an ASCII */ /* string, usually in English, which describes */ /* the typeface's family (like `Times New */ @@ -814,6 +790,19 @@ /* NULL if the field `num_fixed_sizes' is set */ /* to 0. */ /* */ + /* num_charmaps :: The total number of character maps in the */ + /* face. */ + /* */ + /* charmaps :: A table of pointers to the face's charmaps */ + /* Used to scan the list of available charmaps */ + /* this table might change after a call to */ + /* FT_Attach_File/Stream (e.g. when it used */ + /* to hook and additional encoding/CMap to */ + /* the face object). */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* FT_Generic type description. */ + /* */ /* bbox :: The font bounding box. Coordinates are */ /* expressed in font units (see units_per_EM). */ /* The box is large enough to contain any */ @@ -880,6 +869,24 @@ /* underline for this face. Only relevant for */ /* scalable formats. */ /* */ + /* driver :: A handle to the face's parent driver */ + /* object. */ + /* */ + /* memory :: A handle to the face's parent memory */ + /* object. Used for the allocation of */ + /* subsequent objects. */ + /* */ + /* stream :: A handle to the face's stream. */ + /* */ + /* glyph :: The face's associated glyph slot(s). This */ + /* object is created automatically with a new */ + /* face object. However, certain kinds of */ + /* applications (mainly tools like converters) */ + /* can need more than one slot to ease their */ + /* task. */ + /* */ + /* sizes_list :: The list of child sizes for this face. */ + /* */ /* max_points :: The maximum number of points used to store */ /* the vectorial outline of any glyph in this */ /* face. If this value cannot be known in */ @@ -894,37 +901,24 @@ /* this should be set to 0. Only relevant for */ /* scalable formats. */ /* */ + /* transform_matrix :: a 2x2 matrix of 16.16 coefficients used */ + /* to transform glyph outlines after they're */ + /* loaded from the font. Only used by the */ + /* convenience functions. */ + /* */ + /* transform_delta :: a translation vector used to transform */ + /* glyph outlines after they're loaded from */ + /* the font. Only used by the convenience */ + /* functions. */ + /* */ + /* transform_flags :: some flags used to classify the transform. */ + /* Only used by the convenience functions. */ + /* */ typedef struct FT_FaceRec_ { - FT_Driver driver; - FT_Memory memory; - FT_Stream stream; - FT_Long num_faces; FT_Long face_index; - /* a generic pointer for client use */ - FT_Generic generic; - - /* the face's current glyph slot(s) */ - FT_GlyphSlot glyph; - - /* the face's current size, may be nil */ - FT_Size size; - - /* the face's current charmap */ - FT_CharMap charmap; - - /* the face's table of available charmaps */ - FT_Int num_charmaps; - FT_CharMap* charmaps; - - /* the face's current sizes list */ - FT_ListRec sizes_list; - - /* a pointer to the face's extensions block, if supported */ - void* extensions; - FT_Long face_flags; FT_Long style_flags; @@ -936,8 +930,13 @@ FT_Int num_fixed_sizes; FT_Bitmap_Size* available_sizes; - /* the following are only relevant for scalable outlines */ + /* the face's table of available charmaps */ + FT_Int num_charmaps; + FT_CharMap* charmaps; + FT_Generic generic; + + /* the following are only relevant for scalable outlines */ FT_BBox bbox; FT_UShort units_per_EM; @@ -951,9 +950,28 @@ FT_Short underline_position; FT_Short underline_thickness; + /************************************************************/ + /* The following fields should be considered private and */ + /* rarely, if ever, used by client applications.. */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_GlyphSlot glyph; + FT_Size size; + FT_CharMap charmap; + FT_ListRec sizes_list; + + void* extensions; + FT_UShort max_points; FT_Short max_contours; + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; + } FT_FaceRec; @@ -1284,7 +1302,7 @@ FT_Glyph_Metrics metrics; FT_Glyph_Metrics metrics2; - FT_Glyph_Tag format; + FT_Glyph_Format format; FT_Bitmap bitmap; FT_Outline outline; @@ -1347,6 +1365,28 @@ FT_Error FT_Done_FreeType( FT_Library library ); + /*************************************************************************/ + /* */ + /* */ + /* FT_Stream_Type */ + /* */ + /* */ + /* An enumeration used to list the possible ways to open a new */ + /* input stream. It is used by the FT_Open_Args structure.. */ + /* */ + /* */ + /* ft_stream_memory :: this is a memory-based stream */ + /* ft_stream_copy :: copy the stream from the "stream" field */ + /* ft_stream_pathname :: create a new input stream from a C pathname */ + /* */ + typedef enum { + + ft_stream_memory = 1, + ft_stream_copy = 2, + ft_stream_pathname = 3 + + } FT_Stream_Type; + /************************************************************************* * * @@ -1358,6 +1398,8 @@ * function FT_Open_Face & FT_Attach_Stream. * * + * stream_type :: type of input stream + * * memory_base :: first byte of file in memory * memory_size :: size in bytes of file in memory * @@ -1371,28 +1413,30 @@ * the face with each one of the drivers in its list. * * - * Here's how a new input stream is built from a FT_Open_Args - * structure: + * The stream_type determines which fields are used to create a new + * input stream. * - * a/ if 'memory_base' and 'memory_size' are non-null, create a - * memory-based stream from the indicated address and length. + * If it is ft_stream_memory, a new memory-based stream will be created + * using the memory block specified by "memory_base" and "memory_size" * - * b/ Otherwise, if 'pathname' is non NULL, use it to build a - * new system-specific stream (by calling FT_New_Stream) + * If it is ft_stream_pathname, a new stream will be created with the + * "pathname" field, calling the system-specific FT_New_Stream function * - * c/ Otherwise, if 'stream' is non NULL, use it to access the - * font file (note that a new FT_Stream object will be created - * where the contents of 'stream' will be copied). + * It is is ft_stream_copy, then the content of "stream" will be copied + * to a new input stream object. The object will be closed and destroyed + * when the face is destroyed itself.. Note that this means that you + * should not close the stream before the library does !! * *************************************************************************/ typedef struct FT_Open_Args_ { - FT_Byte* memory_base; - FT_Long memory_size; - FT_String* pathname; - FT_Stream stream; - FT_Driver driver; + FT_Stream_Type stream_type; + FT_Byte* memory_base; + FT_Long memory_size; + FT_String* pathname; + FT_Stream stream; + FT_Driver driver; } FT_Open_Args; @@ -1565,46 +1609,6 @@ FT_Error FT_Done_Face( FT_Face face ); - /*************************************************************************/ - /* */ - /* */ - /* FT_New_Size */ - /* */ - /* */ - /* Creates a new size object from a given face object. */ - /* */ - /* */ - /* face :: A handle to a parent face object. */ - /* */ - /* */ - /* size :: A handle to a new size object. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - EXPORT_DEF - FT_Error FT_New_Size( FT_Face face, - FT_Size* size ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Done_Size */ - /* */ - /* */ - /* Discards a given size object. */ - /* */ - /* */ - /* size :: A handle to a target size object */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - EXPORT_DEF - FT_Error FT_Done_Size( FT_Size size ); - - /*************************************************************************/ /* */ /* */ @@ -1657,48 +1661,6 @@ FT_UInt pixel_height ); - /*************************************************************************/ - /* */ - /* */ - /* FT_New_GlyphSlot */ - /* */ - /* */ - /* It is sometimes useful to have more than one glyph slot for a */ - /* given face object. This function is used to create additional */ - /* slots. All of them are automatically discarded when the face is */ - /* destroyed. */ - /* */ - /* */ - /* face :: A handle to a parent face object. */ - /* */ - /* */ - /* slot :: A handle to a new glyph slot object. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - EXPORT_DEF - FT_Error FT_New_GlyphSlot( FT_Face face, - FT_GlyphSlot* aslot ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Done_GlyphSlot */ - /* */ - /* */ - /* Destroys a given glyph slot. Remember however that all slots are */ - /* automatically destroyed with its parent. Using this function is */ - /* not always mandatory. */ - /* */ - /* */ - /* slot :: A handle to a target glyph slot. */ - /* */ - EXPORT_DEF - void FT_Done_GlyphSlot( FT_GlyphSlot slot ); - - /*************************************************************************/ /* */ /* */ @@ -1875,7 +1837,11 @@ /* the values of `num_subglyphs' and `subglyphs', as well as set */ /* `face->glyph.format' to ft_glyph_format_composite. */ /* */ - /* XXXXX : IMPORTANT NOTE, THIS FLAG IS NOT YET IMPLEMENTED !! */ + /* This is for use by the auto-hinter and possibly other tools */ + /* For nearly all applications, this flags should be left unset */ + /* when invoking FT_Load_Glyph(). */ + /* */ + /* Note that the flag forces the load of unscaled glyphs */ /* */ #define FT_LOAD_NO_RECURSE 1024 @@ -1893,36 +1859,6 @@ #define FT_LOAD_DEFAULT 0 - /*************************************************************************/ - /* */ - /* */ - /* FT_Get_Glyph_Bitmap */ - /* */ - /* */ - /* Renders a given glyph into a bitmap or pixmap. This function will */ - /* use the registered rasters to render the glyph image. */ - /* */ - /* */ - /* face :: handle to the face object whose glyph slot contains */ - /* the glyph image */ - /* map :: A pointer to the target bitmap descriptor. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* YES. Rendering is synchronized, so that concurrent calls to the */ - /* scan-line converter will be serialized. */ - /* */ - /* */ - /* This function does NOT CREATE the bitmap, it only renders a */ - /* glyph image into it! */ - /* */ - EXPORT_DEF - FT_Error FT_Get_Glyph_Bitmap( FT_Face face, - FT_Bitmap* map ); - - /*************************************************************************/ /* */ /* */ @@ -2084,6 +2020,75 @@ FT_Long b ); + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* or-ed to the target bitmap. */ + /* */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* outline :: A pointer to the source outline descriptor. */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + EXPORT_DEF + FT_Error FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* map ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* Renders an outline within a bitmap using the current scan-convert */ + /* This functions uses a FT_Raster_Params as argument, allowing */ + /* advanced features like direct composition/translucency, etc.. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* outline :: A pointer to the source outline descriptor. */ + /* params :: A pointer to a FT_Raster_Params used to describe */ + /* the rendering operation */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* You should know what you're doing and the role of FT_Raster_Params */ + /* to use this function. */ + /* */ + /* the field "params.source" will be set to "outline" before the */ + /* scan converter is called, which means that the value you give it */ + /* is actually ignored.. */ + /* */ + EXPORT_DEF + FT_Error FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + /*************************************************************************/ /* */ /* */ @@ -2211,15 +2216,12 @@ /* */ /* cbox :: The outline's control box. */ /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ /* */ /* Yes. */ /* */ EXPORT_DEF - FT_Error FT_Outline_Get_CBox( FT_Outline* outline, - FT_BBox* cbox ); + void FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ); /*************************************************************************/ @@ -2253,23 +2255,79 @@ /* Register a given raster to the library. */ /* */ /* */ - /* library :: A handle to a target library object. */ - /* */ - /* interface :: pointer to the raster's interface */ - /* */ - /* raster :: if this field is nil, this function will allocate */ - /* a new objet. Otherwise, it will simply use the one */ - /* provided here. */ - /* */ - /* Error code. 0 means success. */ + /* library :: A handle to a target library object. */ + /* raster_funcs :: pointer to the raster's interface */ /* */ /* */ /* Error code. 0 means success. */ /* */ + /* */ + /* This function will do the following: */ + /* */ + /* - a new raster object is created through raster_func.raster_new */ + /* if this fails, then the function returns */ + /* */ + /* - if a raster is already registered for the glyph format */ + /* specified in raster_funcs, it will be destroyed */ + /* */ + /* - the new raster is registered for the glyph format */ + /* */ EXPORT_DEF - FT_Error FT_Set_Raster( FT_Library library, - FT_Raster_Interface* interface, - FT_Raster raster ); + FT_Error FT_Set_Raster( FT_Library library, + FT_Raster_Funcs* raster_funcs ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Unset_Raster */ + /* */ + /* */ + /* Removes a given raster from the library. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* raster_funcs :: pointer to the raster's interface */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function should never be used by a normal client application */ + /* as FT_Set_Raster unregisters the previous raster for a given */ + /* glyph format.. */ + /* */ + EXPORT_DEF + FT_Error FT_Unset_Raster( FT_Library library, + FT_Raster_Funcs* raster_funcs ); + + + /************************************************************************* + * + * + * FT_Get_Raster + * + * + * Return a pointer to the raster corresponding to a given glyph + * format tag. + * + * + * library :: handle to source library object + * glyph_format :: glyph format tag + * + * + * raster_funcs :: if this field is not 0, returns a pointer to the + * raster's interface/descriptor.. + * + * + * a pointer to the corresponding raster object. + * + *************************************************************************/ + + EXPORT_DEF + FT_Raster FT_Get_Raster( FT_Library library, + FT_Glyph_Format glyph_format, + FT_Raster_Funcs *raster_funcs ); /*************************************************************************/ @@ -2289,12 +2347,163 @@ /* Error code. 0 means success. */ /* */ EXPORT_DEF - FT_Error FT_Set_Raster_Mode( FT_Library library, - FT_Glyph_Tag format, - const char* mode, - const char* args ); + FT_Error FT_Set_Raster_Mode( FT_Library library, + FT_Glyph_Format format, + const char* mode, + void* args ); + /***************************************************************************/ + /***************************************************************************/ + /***************************************************************************/ + /***** *****/ + /***** C O N V E N I E N C E F U N C T I O N S *****/ + /***** *****/ + /***** *****/ + /***** The following functions are provided as a convenience *****/ + /***** to client applications. However, their compilation might *****/ + /***** be discarded if FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS *****/ + /***** is defined in "config/ftoption.h". *****/ + /***** *****/ + /***************************************************************************/ + /***************************************************************************/ + /***************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Outline_Copy( FT_Outline* source, + FT_Outline* target ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Transform */ + /* */ + /* */ + /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* You can use FT_Outline_Translate() if you need to translate the */ + /* outline's points. */ + /* */ + EXPORT_DEF + void FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverse the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs.. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag ft_outline_reverse_fill in */ + /* the outline's "flags" field.. */ + /* */ + /* It shouldn't be used by a normal client application, unless it */ + /* knows what it's doing.. */ + /* */ + EXPORT_DEF + void FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + EXPORT_DEF + void FT_Vector_Transform( FT_Vector* vector, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + EXPORT_DEF + void FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + EXPORT_DEF + FT_Error FT_Matrix_Invert( FT_Matrix* matrix ); + #ifdef __cplusplus } #endif diff --git a/include/ftglyph.h b/include/ftglyph.h new file mode 100644 index 000000000..cafc24160 --- /dev/null +++ b/include/ftglyph.h @@ -0,0 +1,320 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs.. */ +/* */ +/* Copyright 1996-1999 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. */ +/* */ +/* This file contains the definition of several convenience functions */ +/* that can be used by client applications to easily retrieve glyph */ +/* bitmaps and outlines from a given face. */ +/* */ +/* These functions should be optional if you're writing a font server */ +/* or text layout engine on top of FreeType. However, they are pretty */ +/* handy for many other simple uses of the library.. */ +/* */ +/***************************************************************************/ + +#ifndef FTGLYPH_H +#define FTGLYPH_H + +#include + + typedef enum { + + ft_glyph_type_none = 0, + ft_glyph_type_bitmap = 1, + ft_glyph_type_outline = 2 + + } FT_GlyphType; + + /*********************************************************************** + * + * + * FT_GlyphRec + * + * + * The root glyph structure contains a given glyph image's metrics. + * Note that the FT_Glyph type is a pointer to FT_GlyphRec + * + * + * memory :: a handle to the memory allocator that is used to + * create/clone/destroy this glyph.. + * + * glyph_type :: the glyph type.. + * + * height :: height of glyph image + * width :: width of glyph image + * + * bearingX :: horizontal bearing, this is the distance from the + * the current pen position to the left of the glyph + * + * bearingY :: vertical bearing, this is the distance from the + * current pen position to the top of the glyph + * + * advance :: this is the horizontal or vertical advance for the + * glyph + * + * + * the distances expressed in the metrics are expressed in 26.6 fixed + * float sub-pixels (i.e. 1/64th of pixels). + * + * the vertical bearing has a positive value when the glyph top is + * above the baseline, and negative when it is under.. + * + ***********************************************************************/ + + typedef struct FT_GlyphRec_ + { + FT_Memory memory; + FT_GlyphType glyph_type; + FT_Int height; + FT_Int width; + FT_Int bearingX; + FT_Int bearingY; + FT_Int advance; + + } FT_GlyphRec, *FT_Glyph; + + + /*********************************************************************** + * + * + * FT_BitmapGlyphRec + * + * + * A structure used to describe a bitmap glyph image.. + * Note that the FT_BitmapGlyph type is a pointer to FT_BitmapGlyphRec + * + * + * metrics :: the corresponding glyph metrics + * bitmap :: a descriptor for the bitmap. + * + * + * the "width" and "height" fields of the metrics are expressed in + * 26.6 sub-pixels. However, the width and height in pixels can be + * read directly from "bitmap.width" and "bitmap.height" + * + * this structure is used for both monochrome and anti-aliased + * bitmaps (the bitmap descriptor contains field describing the + * format of the pixel buffer) + * + * the corresponding pixel buffer is always owned by the BitmapGlyph + * and is thus creatde and destroyed with it.. + * + ***********************************************************************/ + + typedef struct FT_BitmapGlyphRec_ + { + FT_GlyphRec metrics; + FT_Int left; + FT_Int top; + FT_Bitmap bitmap; + + } FT_BitmapGlyphRec_, *FT_BitmapGlyph; + + + /*********************************************************************** + * + * + * FT_OutlineGlyphRec + * + * + * A structure used to describe a vectorial outline glyph image.. + * Note that the FT_OutlineGlyph type is a pointer to FT_OutlineGlyphRec + * + * + * metrics :: the corresponding glyph metrics + * outline :: a descriptor for the outline + * + * + * the "width" and "height" fields of the metrics are expressed in + * 26.6 sub-pixels. However, the width and height in pixels can be + * read directly from "bitmap.width" and "bitmap.rows" + * + * the corresponding outline points tables is always owned by the + * object and are destroyed with it.. + * + * an OutlineGlyph can be used to generate a BitmapGlyph with the + * function FT_OutlineGlyph_Render() + * + ***********************************************************************/ + + typedef struct FT_OutlineGlyphRec_ + { + FT_GlyphRec metrics; + FT_Outline outline; + + } FT_OutlineGlyphRec_, *FT_OutlineGlyph; + + + /*********************************************************************** + * + * + * FT_Get_Glyph_Bitmap + * + * + * A function used to directly return a monochrome bitmap glyph image + * from a face. + * + * + * face :: handle to source face object + * glyph_index :: glyph index in face + * load_flags :: load flags, see FT_LOAD_FLAG_XXXX constants.. + * grays :: number of gray levels for anti-aliased bitmaps, + * set to 0 if you want to render a monochrome bitmap + * origin :: a pointer to the origin's position. Set to 0 + * if the current transform is the identity.. + * + * + * bitglyph :: pointer to the new bitmap glyph + * + * + * Error code. 0 means success. + * + * + * If the font contains glyph outlines, these will be automatically + * converted to a bitmap according to the value of "grays" + * + * If "grays" is set to 0, the result is a 1-bit monochrome bitmap + * otherwise, it is an 8-bit gray-level bitmap + * + * The number of gray levels in the result anti-aliased bitmap might + * not be "grays", depending on the current scan-converter implementation + * + * Note that it is not possible to generate 8-bit monochrome bitmaps + * with this function. Rather, use FT_Get_Glyph_Outline, then + * FT_Glyph_Render_Outline and provide your own span callbacks.. + * + * When the face doesn't contain scalable outlines, this function will + * fail if the current transform is not the identity, or if the glyph + * origin's phase to the pixel grid is not 0 in both directions !! + * + ***********************************************************************/ + + EXPORT_DEF + FT_Error FT_Get_Glyph_Bitmap( FT_Face face, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Int grays, + FT_Vector* origin, + FT_BitmapGlyph *abitglyph ); + + + /*********************************************************************** + * + * + * FT_Get_Glyph_Outline + * + * + * A function used to directly return a bitmap glyph image from a + * face. This is faster than calling FT_Load_Glyph+FT_Get_Outline_Bitmap.. + * + * + * face :: handle to source face object + * glyph_index :: glyph index in face + * load_flags :: load flags, see FT_LOAD_FLAG_XXXX constants.. + * + * + * vecglyph :: pointer to the new outline glyph + * + * + * Error code. 0 means success. + * + * + * If the glyph is not an outline in the face, this function will + * fail.. + * + * This function will fail if the load flags FT_LOAD_NO_OUTLINE and + * FT_LOAD_NO_RECURSE are set.. + * + ***********************************************************************/ + + EXPORT_DEF + FT_Error FT_Get_Glyph_Outline( FT_Face face, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_OutlineGlyph *vecglyph ); + + + /*********************************************************************** + * + * + * FT_Set_Transform + * + * + * A function used to set the transform that is applied to glyph images + * just after they're loaded in the face's glyph slot, and before they're + * returned by either FT_Get_Glyph_Bitmap or FT_Get_Glyph_Outline + * + * + * face :: handle to source face object + * matrix :: pointer to the transform's 2x2 matrix. 0 for identity + * delta :: pointer to the transform's translation. 0 for null vector + * + * + * The transform is only applied to glyph outlines when they are found + * in a font face. It is unable to transform embedded glyph bitmaps + * + ***********************************************************************/ + + EXPORT_DEF + void FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*********************************************************************** + * + * + * FT_Done_Glyph + * + * + * Destroys a given glyph.. + * + * + * glyph :: handle to target glyph object + * + ***********************************************************************/ + + EXPORT_DEF + void FT_Done_Glyph( FT_Glyph glyph ); + + + /*********************************************************************** + * + * + * FT_Glyph_Get_Box + * + * + * Returns the glyph image's bounding box in pixels. + * + * + * glyph :: handle to target glyph object + * + * + * box :: the glyph bounding box. Coordinates are expressed in + * _integer_ pixels, with exclusive max bounds + * + * + * Coordinates are relative to the glyph origin, using the Y-upwards + * convention.. + * + * The width of the box in pixels is box.xMax-box.xMin + * The height is box.yMax - box.yMin + * + ***********************************************************************/ + + EXPORT_DEF + void FT_Glyph_Get_Box( FT_Glyph glyph, + FT_BBox *box ); + +#endif /* FTGLYPH_H */ diff --git a/include/ftimage.h b/include/ftimage.h index 527071ec0..9e8f5d427 100644 --- a/include/ftimage.h +++ b/include/ftimage.h @@ -470,8 +470,6 @@ } FT_Outline_Funcs; - - /*************************************************************************/ /* */ /* */ @@ -491,7 +489,7 @@ /*********************************************************************** * * - * FT_Glyph_Tag + * FT_Glyph_Format * * * An enumeration type used to describethe format of a given glyph @@ -518,7 +516,7 @@ * ***********************************************************************/ - typedef enum FT_Glyph_Tag_ + typedef enum FT_Glyph_Format_ { ft_glyph_format_none = 0, ft_glyph_format_composite = FT_IMAGE_TAG('c','o','m','p'), @@ -526,8 +524,28 @@ ft_glyph_format_outline = FT_IMAGE_TAG('o','u','t','l'), ft_glyph_format_plotter = FT_IMAGE_TAG('p','l','o','t') - } FT_Glyph_Tag; + } FT_Glyph_Format; + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** R A S T E R D E F I N I T I O N S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /************************************************************************** + * + * + * + * + * + * + * + * + **************************************************************************/ /*************************************************************************/ /* */ @@ -543,126 +561,374 @@ /*************************************************************************/ /* */ - /* */ - /* FT_Raster_Init_Proc */ + /* */ + /* FT_Span */ /* */ /* */ - /* Initializes a fresh raster object which should have been allocated */ - /* by client applications. This function is also used to set the */ - /* object's render pool. It can be used repeatedly on a single */ - /* object if one wants to change the pool's address or size. */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monocrhome or anti-aliased bitmap. */ /* */ - /* Note that the render pool has no state and is only used during a */ - /* call to FT_Raster_Render(). It is thus theorically possible to */ - /* share it between several non-concurrent components of your */ - /* applications when memory is a scarce resource. */ + /* */ + /* x :: the span's horizontal start position */ + /* len :: the span's length in pixels */ + /* coverage :: the span color/coverage, ranging from 0 (background) */ + /* to 255 (foreground). Only used for anti-aliased */ + /* rendering.. */ /* */ - /* */ - /* raster :: a handle to the target raster object. */ - /* pool_base :: the render pool's base address in memory */ - /* pool_size :: the render pool's size in bytes. this must be at */ - /* least 4 kByte. */ - /* */ - /* An error condition, used as a FT_Error in the FreeType library. */ - /* 0 means success. */ + /* */ + /* This structure is used by the span drawing callback type */ + /* named FT_Raster_Span_Func, which takes the y coordinate of the */ + /* span as a paremeter.. */ /* */ - typedef int (*FT_Raster_Init_Proc)( FT_Raster raster, - const char* pool_base, - long pool_size ); + /* The coverage value is always between 0 and 255, even if the */ + /* number of gray levels have been set through FT_Set_Gray_Levels() */ + /* */ + typedef struct FT_Span_ + { + short x; + short len; + unsigned char coverage; + + } FT_Span; /*************************************************************************/ /* */ /* */ - /* FT_Raster_Set_Mode_Proc */ + /* FT_Raster_Span_Func */ /* */ /* */ - /* Some raster implementations may have several modes of operation. */ - /* This function is used to select one of them, as well as pass some */ - /* arguments. */ + /* A function used as a call-back by the anti-aliased renderer in */ + /* order to let client applications draw themselves the gray pixel */ + /* spans on each scan line. */ /* */ /* */ - /* raster :: The target raster object. */ + /* y :: the scanline's y coordinate */ + /* count :: the number of spans to draw on this scanline */ + /* spans :: a table of 'count' spans to draw on the scanline */ + /* user :: user-supplied data that is passed to the callback */ /* */ - /* mode :: A pointer used to describe the mode to set. This is */ - /* completely raster-specific, and could be, for example, */ - /* a text string. */ + /* */ + /* This callback allows client applications to directly render the */ + /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ /* */ - /* args :: An argument to the set_mode command. This is completely */ - /* specific to the raster and the mode used. */ + /* This can be used to write anti-aliased outlines directly to a */ + /* given background bitmap, and even perform translucency.. */ + /* */ + /* Note that the "count" field cannot be greater than a fixed value */ + /* defined by the FT_MAX_GRAY_SPANS configuration macro in ftoption.h */ + /* */ + /* By default, this value is set to 32, which means that if there are */ + /* more than 32 spans on a given scanline, the callback will be called */ + /* several times with the same "y" parameter in order to draw all */ + /* callbacks.. */ + /* */ + /* Otherwise, the callback is only called once per scan-line, and */ + /* only for those scanlines that do have "gray" pixels on them.. */ + /* */ + typedef void (*FT_Raster_Span_Func)( int y, + int count, + FT_Span* spans, + void* user ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitTest_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to test wether a given target pixel is already set to the drawing */ + /* "color". These tests are crucial to implement drop-out control */ + /* per-se the TrueType spec.. */ + /* */ + /* */ + /* y :: the pixel's y coordinate */ + /* x :: the pixel's x coordinate */ + /* user :: user-supplied data that is passed to the callback */ /* */ /* */ - /* An error code, used as a FT_Error by the FreeType library. */ - /* 0 means success. */ + /* 1 if the pixel is "set", 0 otherwise */ /* */ - typedef int (*FT_Raster_Set_Mode_Proc)( FT_Raster raster, + typedef int (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitSet_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* used to set an individual target pixel. This is crucial to */ + /* implement drop-out control per-se the TrueType spec.. */ + /* */ + /* */ + /* y :: the pixel's y coordinate */ + /* x :: the pixel's x coordinate */ + /* user :: user-supplied data that is passed to the callback */ + /* */ + /* */ + /* 1 if the pixel is "set", 0 otherwise */ + /* */ + typedef void (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /************************************************************************** + * + * + * FT_Raster_Flag + * + * + * An enumeration used to list the bit flags used in the "flags" + * field of a FT_Raster_Params function. + * + * + * ft_raster_flag_default :: this value is 0 + * + * ft_raster_flag_aa :: resquests the rendering of an anti-aliased + * glyph bitmap. If unset, a monchrome bitmap + * will be rendered. + * + * ft_raster_flag_direct :: requests direct rendering over the target + * bitmap. Direct rendering uses user-provided + * callbacks in order to perform direct + * drawing or composition over an existing + * bitmap. If this bit is unset, the content + * of the target bitmap **must be zeroed** ! + * + **************************************************************************/ + typedef enum { + + ft_raster_flag_default = 0, + ft_raster_flag_aa = 1, + ft_raster_flag_direct = 2 + + } FT_Raster_Flag; + + /************************************************************************** + * + * + * FT_Raster_Params + * + * + * A structure used to hold the arguments used by a raster's render + * function. + * + * + * target :: the target bitmap + * source :: pointer to the source glyph image (e.g. a FT_Outline) + * flags :: rendering flags + * gray_spans :: gray span drawing callback + * black_spans :: black span drawing callback + * bit_test :: bit test callback + * bit_set :: bit set callback + * user :: user-supplied data that is passed to each drawing + * callback.. + * + * + * An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit + * flag is set in the "flags" field, otherwise a monochrome bitmap will + * be generated. + * + * When the ft_raster_flag_direct bit flag is set in "flags", the raster + * will call the "gray_spans" callback to drawn gray pixel spans, in the + * case of an aa glyph bitmap, or "black_spans", "bit_test" and "bit_set" + * in the case of a monochrome bitmap. + * + * This allows direct composition over a pre-existing bitmap through + * user-provided callbacks to perform the span drawing/composition. + * + * Note that the "bit_test" and "bit_set" callbacks are required when + * rendering a monochrome bitmap, as they are crucial to implement correct + * drop-out control per-se the TrueType specification.. + * + **************************************************************************/ + + typedef struct FT_Raster_Params_ + { + FT_Bitmap* target; + void* source; + int flags; + FT_Raster_Span_Func gray_spans; + FT_Raster_Span_Func black_spans; + FT_Raster_BitTest_Func bit_test; + FT_Raster_BitSet_Func bit_set; + void* user; + + } FT_Raster_Params; + + + + /************************************************************************** + * + * FT_Raster_New_Func + * + * + * A function used to create a new raster object. + * + * + * memory :: handle to memory allocator. + * + * + * raster :: handle to new raster object + * + * + * Error code. 0 means success + * + * + * the "memory" parameter is a typeless pointer in order to avoid + * un-wanted dependencies on the rest of the FreeType code. + * + * in practice, it is a FT_Memory, i.e. a handle to the standard + * FreeType memory allocator. However, this field can be completely + * ignored by a given raster implementation.. + * + **************************************************************************/ + + typedef int (*FT_Raster_New_Func)( void* memory, + FT_Raster *raster ); + + + /************************************************************************** + * + * FT_Raster_Done_Func + * + * + * A function used to destroy a given raster object. + * + * + * raster :: handle to new raster object + * + **************************************************************************/ + + typedef void (*FT_Raster_Done_Func)( FT_Raster raster ); + + + + /************************************************************************** + * + * + * FT_Raster_Reset_Func + * + * + * FreeType provides an area of memory called the "render pool", + * available to all registered rasters. This pool can be freely + * used during a given scan-conversion but is shared by all rasters. + * Its content is thus transient. + * + * This function is called each time the render pool changes, or + * just after a new raster object is created. + * + * + * raster :: handle to new raster object + * pool_base :: address in memory of render pool + * pool_size :: size in bytes of render pool + * + * + * Rasters can ignore the render pool and rely on dynamic memory + * allocation if they want to (a handle to the memory allocator is + * passed to the raster constructor). However, this is not recommended + * for efficiency purposes.. + * + **************************************************************************/ + + typedef void (*FT_Raster_Reset_Func)( FT_Raster raster, + const char* pool_base, + long pool_size ); + + + /************************************************************************** + * + * + * FT_Raster_Set_Mode_Func + * + * + * This function is a generic facility to change modes or attributes + * in a given raster. This can be used for debugging purposes, or + * simply to allow implementation-specific "features" in a given + * raster module. + * + * + * raster :: handle to new raster object + * mode :: an C string naming the mode or property to change + * args :: a pointer to the new mode/property to use + * + **************************************************************************/ + + typedef int (*FT_Raster_Set_Mode_Func)( FT_Raster raster, const char* mode, - const char* args ); - - - /************************************************************************* - * - * - * FT_Raster_Render_Proc - * - * - * Renders an outline into a target bitmap/pixmap. - * - * - * raster :: A handle to a raster object used during rendering. - * - * source_image :: a typeless pointer to the source glyph image. - * (usually a FT_Outline*). - * - * target_bitmap :: descriptor to the target bitmap. - * - * - * Error code, interpreted as a FT_Error by FreeType library. - * 0 means success. - * - *************************************************************************/ - - typedef int (*FT_Raster_Render_Proc)( FT_Raster raster, - void* source_image, - FT_Bitmap* target_bitmap ); + void* args ); + + /************************************************************************** + * + * + * FT_Raster_Render_Func + * + * + * Invokes a given raster to scan-convert a given glyph image into + * a target bitmap. + * + * + * raster :: handle to raster object + * params :: pointer to a FT_Raster_Params structure used to store + * the rendering parameters. + * + * + * Error code. 0 means success + * + * + * The exact format of the source image depends on the raster's + * glyph format defined in its FT_Raster_Funcs structure. It can be + * an FT_Outline or anything else in order to support a large array + * of glyph formats. + * + * Note also that the render function can fail and return a + * FT_Err_Unimplemented_Feature error code when the raster used does + * not support direct composition. + * + * XXX: For now, the standard raster doesn't support direct composition + * but this should change for the final release (see the files + * demos/src/ftgrays.c and demos/src/ftgrays2.c for examples of + * distinct implementations which support direct composition). + * + **************************************************************************/ + + typedef int (*FT_Raster_Render_Func)( FT_Raster raster, + FT_Raster_Params* params ); /************************************************************************** * * - * FT_Raster_Interface + * FT_Raster_Funcs * * - * A structure used to model the default raster interface. A raster - * is a module in charge of converting a glyph image into a bitmap. - * + * A structure used to describe a given raster class to the library. + * * - * size :: the size in bytes of the given raster object. This - * is used to allocate a new raster when calling - * `FT_Set_Raster'. - * - * format :: the source glyph image format this raster is able to - * handle. - * - * init :: the raster's initialisation routine - * - * set_mode :: the raster's mode set routine - * - * render :: the raster's rendering routine + * glyph_format :: the supported glyph format for this raster + * raster_new :: the raster constructor + * raster_reset :: used to reset the render pool within the raster + * raster_render :: renders a glyph into a given bitmap + * raster_done :: the raster destructor * **************************************************************************/ - - typedef struct FT_Raster_Interface_ - { - long size; - FT_Glyph_Tag format_tag; - FT_Raster_Init_Proc init; - FT_Raster_Set_Mode_Proc set_mode; - FT_Raster_Render_Proc render; - - - } FT_Raster_Interface; + + typedef struct FT_Raster_Funcs_ + { + FT_Glyph_Format glyph_format; + FT_Raster_New_Func raster_new; + FT_Raster_Reset_Func raster_reset; + FT_Raster_Set_Mode_Func raster_set_mode; + FT_Raster_Render_Func raster_render; + FT_Raster_Done_Func raster_done; + + } FT_Raster_Funcs; #endif /* FTIMAGE_H */ diff --git a/include/ftraster.h b/include/ftraster.h index 1e0ecb3c6..0ba630b24 100644 --- a/include/ftraster.h +++ b/include/ftraster.h @@ -38,25 +38,7 @@ #endif EXPORT_DEF - int FT_Raster_Init( FT_Raster raster, - const char* pool_base, - long pool_size ); - - EXPORT_DEF - int FT_Raster_Render( FT_Raster raster, - FT_Outline* outline, - FT_Bitmap* target_map ); - - EXPORT_DEF - long FT_Raster_ObjSize( void ); - - /* FT_Raster_SetPalette() is currently unused by FreeType 2 */ - - EXPORT_DEF - int FT_Raster_SetPalette( FT_Raster raster, - int count, - const char* palette ); - + FT_Raster_Funcs ft_raster_funcs; #ifdef __cplusplus } diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c new file mode 100644 index 000000000..c7ffe8c41 --- /dev/null +++ b/src/base/ftglyph.c @@ -0,0 +1,500 @@ +/***************************************************************************/ +/* */ +/* ftglyph.c */ +/* */ +/* FreeType convenience functions to handle glyphs.. */ +/* */ +/* Copyright 1996-1999 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. */ +/* */ +/* This file contains the definition of several convenience functions */ +/* that can be used by client applications to easily retrieve glyph */ +/* bitmaps and outlines from a given face. */ +/* */ +/* These functions should be optional if you're writing a font server */ +/* or text layout engine on top of FreeType. However, they are pretty */ +/* handy for many other simple uses of the library.. */ +/* */ +/***************************************************************************/ + +#include +#include + + static + void ft_prepare_glyph( FT_Glyph glyph, + FT_Face face, + FT_Bool vertical ) +{ + FT_Glyph_Metrics* metrics = &face->glyph->metrics; + + glyph->memory = face->memory; + glyph->width = metrics->width; + glyph->height = metrics->height; + + if (vertical) + { + glyph->bearingX = metrics->vertBearingX; + glyph->bearingY = metrics->vertBearingY; + glyph->advance = metrics->vertAdvance; + } + else + { + glyph->bearingX = metrics->horiBearingX; + glyph->bearingY = metrics->horiBearingY; + glyph->advance = metrics->horiAdvance; + } + } + + /*********************************************************************** + * + * + * FT_Get_Glyph_Bitmap + * + * + * A function used to directly return a monochrome bitmap glyph image + * from a face. + * + * + * face :: handle to source face object + * glyph_index :: glyph index in face + * load_flags :: load flags, see FT_LOAD_FLAG_XXXX constants.. + * grays :: number of gray levels for anti-aliased bitmaps, + * set to 0 if you want to render a monochrome bitmap + * origin :: a pointer to the origin's position. Set to 0 + * if the current transform is the identity.. + * + * + * bitglyph :: pointer to the new bitmap glyph + * + * + * Error code. 0 means success. + * + * + * If the font contains glyph outlines, these will be automatically + * converted to a bitmap according to the value of "grays" + * + * If "grays" is set to 0, the result is a 1-bit monochrome bitmap + * otherwise, it is an 8-bit gray-level bitmap + * + * The number of gray levels in the result anti-aliased bitmap might + * not be "grays", depending on the current scan-converter implementation + * + * Note that it is not possible to generate 8-bit monochrome bitmaps + * with this function. Rather, use FT_Get_Glyph_Outline, then + * FT_Glyph_Render_Outline and provide your own span callbacks.. + * + * When the face doesn't contain scalable outlines, this function will + * fail if the current transform is not the identity, or if the glyph + * origin's phase to the pixel grid is not 0 in both directions !! + * + ***********************************************************************/ + + EXPORT_FUNC + FT_Error FT_Get_Glyph_Bitmap( FT_Face face, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Int grays, + FT_Vector* origin, + FT_BitmapGlyph *abitglyph ) + { + FT_Error error; + FT_Memory memory; + FT_BitmapGlyph bitglyph; + FT_Glyph glyph; + FT_Pos origin_x = 0; + FT_Pos origin_y = 0; + + *abitglyph = 0; + + if (origin) + { + origin_x = origin->x & 63; + origin_y = origin->y & 63; + } + + /* check arguments if the face's format is not scalable */ + if ( !(face->face_flags & FT_FACE_FLAG_SCALABLE) && face->transform_flags ) + { + /* we can't transform bitmaps, so return an error */ + error = FT_Err_Unimplemented_Feature; + goto Exit; + } + + /* check that NO_SCALE and NO_RECURSE are not set */ + if (load_flags & (FT_LOAD_NO_SCALE|FT_LOAD_NO_RECURSE)) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* disable embedded bitmaps for transformed images */ + if ( face->face_flags & FT_FACE_FLAG_SCALABLE && face->transform_flags ) + load_flags |= FT_LOAD_NO_BITMAP; + + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if (error) goto Exit; + + /* now, handle bitmap and outline glyph images */ + memory = face->memory; + switch ( face->glyph->format ) + { + case ft_glyph_format_bitmap: + { + FT_Long size; + FT_Bitmap* source; + + if ( ALLOC( bitglyph, sizeof(*bitglyph) ) ) + goto Exit; + + glyph = (FT_Glyph)bitglyph; + glyph->glyph_type = ft_glyph_type_bitmap; + ft_prepare_glyph( glyph, face, 0 ); + + source = &face->glyph->bitmap; + size = source->rows * source->pitch; + if (size < 0) size = -size; + + bitglyph->bitmap = *source; + if ( ALLOC( bitglyph->bitmap.buffer, size ) ) + goto Fail; + + /* copy the content of the source glyph */ + MEM_Copy( bitglyph->bitmap.buffer, source->buffer, size ); + } + break; + + case ft_glyph_format_outline: + { + FT_BBox cbox; + FT_Int width, height, pitch; + FT_Long size; + + /* transform the outline - note that the original metrics are NOT */ + /* transformed by this.. only the outline points themselves.. */ + FT_Outline_Transform( &face->glyph->outline, &face->transform_matrix ); + FT_Outline_Translate( &face->glyph->outline, + face->transform_delta.x + origin_x, + face->transform_delta.y + origin_y ); + + /* compute the size in pixels of the outline */ + FT_Outline_Get_CBox( &face->glyph->outline, &cbox ); + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = (cbox.xMax+63) & -64; + cbox.yMax = (cbox.yMax+63) & -64; + + width = (cbox.xMax - cbox.xMin) >> 6; + height = (cbox.yMax - cbox.yMin) >> 6; + + /* allocate the pixel buffer for the glyph bitmap */ + if (grays) pitch = (width+3) & -4; /* some raster implementation need this */ + else pitch = (width+7) >> 3; + + size = pitch * height; + if ( ALLOC( bitglyph, sizeof(*bitglyph) ) ) + goto Exit; + + glyph = (FT_Glyph)bitglyph; + glyph->glyph_type = ft_glyph_type_bitmap; + ft_prepare_glyph( glyph, face, 0 ); + + if ( ALLOC( bitglyph->bitmap.buffer, size ) ) + goto Fail; + + bitglyph->bitmap.width = width; + bitglyph->bitmap.rows = height; + bitglyph->bitmap.pitch = pitch; + bitglyph->bitmap.pixel_mode = grays ? ft_pixel_mode_grays + : ft_pixel_mode_mono; + bitglyph->bitmap.num_grays = (short)grays; + + bitglyph->left = (cbox.xMin >> 6); + bitglyph->top = (cbox.yMax >> 6); + + /* render the monochrome outline into the target buffer */ + FT_Outline_Translate( &face->glyph->outline, -cbox.xMin, -cbox.yMin ); + error = FT_Outline_Get_Bitmap( face->driver->library, + &face->glyph->outline, + &bitglyph->bitmap ); + if (error) + { + FREE( bitglyph->bitmap.buffer ); + goto Fail; + } + } + break; + + default: + error = FT_Err_Invalid_Glyph_Index; + goto Exit; + } + + *abitglyph = bitglyph; + Exit: + return error; + + Fail: + FREE( glyph ); + goto Exit; + } + + + /*********************************************************************** + * + * + * FT_Get_Glyph_Outline + * + * + * A function used to directly return a bitmap glyph image from a + * face. This is faster than calling FT_Load_Glyph+FT_Get_Outline_Bitmap.. + * + * + * face :: handle to source face object + * glyph_index :: glyph index in face + * load_flags :: load flags, see FT_LOAD_FLAG_XXXX constants.. + * + * + * vecglyph :: pointer to the new outline glyph + * + * + * Error code. 0 means success. + * + * + * This function will fail if the load flags FT_LOAD_NO_OUTLINE and + * FT_LOAD_NO_RECURSE are set.. + * + ***********************************************************************/ + + EXPORT_FUNC + FT_Error FT_Get_Glyph_Outline( FT_Face face, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_OutlineGlyph *vecglyph ) + { + FT_Error error; + FT_Memory memory; + FT_OutlineGlyph glyph; + + *vecglyph = 0; + + /* check that NO_OUTLINE and NO_RECURSE are not set */ + if (load_flags & (FT_LOAD_NO_OUTLINE|FT_LOAD_NO_RECURSE)) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* disable the loading of embedded bitmaps */ + load_flags |= FT_LOAD_NO_BITMAP; + + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if (error) goto Exit; + + /* check that we really loaded an outline */ + if ( face->glyph->format != ft_glyph_format_outline ) + { + error = FT_Err_Invalid_Glyph_Index; + goto Exit; + } + + /* transform the outline - note that the original metrics are NOT */ + /* transformed by this.. only the outline points themselves.. */ + if ( face->transform_flags ) + { + FT_Outline_Transform( &face->glyph->outline, &face->transform_matrix ); + FT_Outline_Translate( &face->glyph->outline, + face->transform_delta.x, + face->transform_delta.y ); + } + + /* now, create a new outline glyph and copy everything there */ + memory = face->memory; + if ( ALLOC( glyph, sizeof(*glyph) ) ) + goto Exit; + + ft_prepare_glyph( (FT_Glyph)glyph, face, 0 ); + glyph->metrics.glyph_type = ft_glyph_type_outline; + + error = FT_Outline_New( face->driver->library, + face->glyph->outline.n_points, + face->glyph->outline.n_contours, + &glyph->outline ); + if (!error) + error = FT_Outline_Copy( &face->glyph->outline, &glyph->outline ); + + if (error) goto Fail; + + *vecglyph = glyph; + Exit: + return error; + + Fail: + FREE( glyph ); + goto Exit; + } + + /*********************************************************************** + * + * + * FT_Set_Transform + * + * + * A function used to set the transform that is applied to glyph images + * just after they're loaded in the face's glyph slot, and before they're + * returned by either FT_Get_Glyph_Bitmap or FT_Get_Glyph_Outline + * + * + * face :: handle to source face object + * matrix :: pointer to the transform's 2x2 matrix. 0 for identity + * delta :: pointer to the transform's translation. 0 for null vector + * + * + * The transform is only applied to glyph outlines when they are found + * in a font face. It is unable to transform embedded glyph bitmaps + * + ***********************************************************************/ + + EXPORT_FUNC + void FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + face->transform_flags = 0; + + if (!matrix) + { + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0L; + face->transform_matrix.yy = 0x10000L; + matrix = &face->transform_matrix; + } + else + face->transform_matrix = *matrix; + + /* set transform_flags bit flag 0 if delta isn't the null vector */ + if ( (matrix->xy | matrix->yx) || + matrix->xx != 0x10000L || + matrix->yy != 0x10000L ) + face->transform_flags |= 1; + + if (!delta) + { + face->transform_delta.x = 0; + face->transform_delta.y = 0; + delta = &face->transform_delta; + } + else + face->transform_delta = *delta; + + /* set transform_flags bit flag 1 if delta isn't the null vector */ + if ( delta->x | delta->y ) + face->transform_flags |= 2; + } + + /*********************************************************************** + * + * + * FT_Done_Glyph + * + * + * Destroys a given glyph.. + * + * + * glyph :: handle to target glyph object + * + ***********************************************************************/ + + EXPORT_FUNC + void FT_Done_Glyph( FT_Glyph glyph ) + { + if (glyph) + { + FT_Memory memory = glyph->memory; + + if ( glyph->glyph_type == ft_glyph_type_bitmap ) + { + FT_BitmapGlyph bit = (FT_BitmapGlyph)glyph; + FREE( bit->bitmap.buffer ); + } + else if ( glyph->glyph_type == ft_glyph_type_outline ) + { + FT_OutlineGlyph out = (FT_OutlineGlyph)glyph; + if (out->outline.flags & ft_outline_owner) + { + FREE( out->outline.points ); + FREE( out->outline.contours ); + FREE( out->outline.tags ); + } + } + + FREE( glyph ); + } + } + + + /*********************************************************************** + * + * + * FT_Glyph_Get_Box + * + * + * Returns the glyph image's bounding box in pixels. + * + * + * glyph :: handle to target glyph object + * + * + * box :: the glyph bounding box. Coordinates are expressed in + * _integer_ pixels, with exclusive max bounds + * + * + * Coordinates are relative to the glyph origin, using the Y-upwards + * convention.. + * + * The width of the box in pixels is box.xMax-box.xMin + * The height is box.yMax - box.yMin + * + ***********************************************************************/ + + EXPORT_DEF + void FT_Glyph_Get_Box( FT_Glyph glyph, + FT_BBox *box ) + { + box->xMin = box->xMax = 0; + box->yMin = box->yMax = 0; + + if (glyph) switch (glyph->glyph_type) + { + case ft_glyph_type_bitmap: + { + FT_BitmapGlyph bit = (FT_BitmapGlyph)glyph; + box->xMin = bit->left; + box->xMax = box->xMin + bit->bitmap.width; + box->yMax = bit->top; + box->yMin = box->yMax - bit->bitmap.rows; + } + break; + + case ft_glyph_type_outline: + { + FT_OutlineGlyph out = (FT_OutlineGlyph)glyph; + + FT_Outline_Get_CBox( &out->outline, box ); + box->xMin >>= 6; + box->yMin >>= 6; + box->xMax = (box->xMax+63) >> 6; + box->yMax = (box->yMax+63) >> 6; + } + break; + + default: + ; + } + } diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 58cca87c0..30f6257f7 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -220,48 +220,58 @@ static FT_Error ft_new_input_stream( FT_Library library, FT_Open_Args* args, - FT_Stream* astream ) + FT_Stream *astream ) { FT_Error error; FT_Memory memory; FT_Stream stream; - - memory = library->memory; + *astream = 0; + memory = library->memory; if ( ALLOC( stream, sizeof ( *stream ) ) ) - return error; + goto Exit; stream->memory = memory; - /* is it a memory stream? */ - if ( args->memory_base && args->memory_size ) - FT_New_Memory_Stream( library, - args->memory_base, - args->memory_size, - stream ); - - /* do we have an 8-bit pathname? */ - else if ( args->pathname ) + /* now, look at the stream type */ + switch ( args->stream_type ) { - error = FT_New_Stream( args->pathname, stream ); - stream->pathname.pointer = args->pathname; - } - - /* do we have a custom stream? */ - else if ( args->stream ) - { - /* copy the contents of the argument stream */ - /* into the new stream object */ - *stream = *(args->stream); - stream->memory = memory; - } - else - error = FT_Err_Invalid_Argument; + /***** is it a memory-based stream ? *****************************/ + case ft_stream_memory: + { + FT_New_Memory_Stream( library, + args->memory_base, + args->memory_size, + stream ); + break; + } + /***** is is a pathname stream ? ********************************/ + case ft_stream_pathname: + { + error = FT_New_Stream( args->pathname, stream ); + stream->pathname.pointer = args->pathname; + break; + } + + case ft_stream_copy: + { + if ( args->stream) + { + *stream = *(args->stream); + stream->memory = memory; + break; + } + } + default: + error = FT_Err_Invalid_Argument; + } + if ( error ) FREE( stream ); *astream = stream; + Exit: return error; } @@ -280,7 +290,6 @@ FT_Stream stream = *astream; FT_Memory memory = stream->memory; - if ( stream->close ) stream->close( stream ); @@ -387,110 +396,171 @@ } - /*************************************************************************/ - /* */ - /* */ - /* FT_Get_Glyph_Format */ - /* */ - /* */ - /* Gets the glyph format for a given format tag. */ - /* */ - /* */ - /* library :: A handle to the library object. */ - /* format_tag :: A tag identifying the glyph format. */ - /* */ - /* */ - /* A pointer to a glyph format. 0 if `format_tag' isn't defined. */ - /* */ - BASE_FUNC - FT_Glyph_Format* FT_Get_Glyph_Format( FT_Library library, - FT_Glyph_Tag format_tag ) + /************************************************************************* + * + * + * FT_Get_Raster + * + * + * Return a pointer to the raster corresponding to a given glyph + * format tag. + * + * + * library :: handle to source library object + * glyph_format :: glyph format tag + * + * + * raster_funcs :: if this field is not 0, returns the raster's interface + * + * + * a pointer to the corresponding raster object. + * + *************************************************************************/ + + EXPORT_FUNC + FT_Raster FT_Get_Raster( FT_Library library, + FT_Glyph_Format glyph_format, + FT_Raster_Funcs *raster_funcs ) { - FT_Glyph_Format* cur = library->glyph_formats; - FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; - - - for ( ; cur < limit; cur ++ ) + FT_Int n; + + for ( n = 0; n < FT_MAX_GLYPH_FORMATS; n++ ) { - if ( cur->format_tag == format_tag ) - return cur; + FT_Raster_Funcs* funcs = &library->raster_funcs[n]; + if (funcs->glyph_format == glyph_format) + { + if (raster_funcs) + *raster_funcs = *funcs; + return library->rasters[n]; + } } - return 0; } - /*************************************************************************/ /* */ /* */ /* FT_Set_Raster */ /* */ /* */ - /* This function changes the raster module used to convert from a */ - /* given memory object. It is thus possible to use libraries with */ - /* distinct memory allocators within the same program. */ + /* Register a given raster to the library. */ /* */ /* */ - /* library :: A handle to the library object. */ - /* interface :: A pointer to the interface of the new raster module. */ - /* */ - /* */ - /* raster :: A handle to the raster object. */ + /* library :: A handle to a target library object. */ + /* raster_funcs :: pointer to the raster's interface */ /* */ /* */ - /* FreeType error code. 0 means success. */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function will do the following: */ + /* */ + /* - a new raster object is created through raster_func.raster_new */ + /* if this fails, then the function returns */ + /* */ + /* - if a raster is already registered for the glyph format */ + /* specified in raster_funcs, it will be destroyed */ + /* */ + /* - the new raster is registered for the glyph format */ /* */ EXPORT_FUNC - FT_Error FT_Set_Raster( FT_Library library, - FT_Raster_Interface* interface, - FT_Raster raster ) + FT_Error FT_Set_Raster( FT_Library library, + FT_Raster_Funcs* raster_funcs ) { - FT_Memory memory = library->memory; - FT_Error error = FT_Err_Ok; - FT_Glyph_Format* format; - - - /* allocate the render pool if necessary */ - if ( !library->raster_pool && - ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) - goto Exit; - - /* find the glyph formatter for the raster's format */ - format = FT_Get_Glyph_Format( library, interface->format_tag ); - if ( !format ) + FT_Glyph_Format glyph_format = raster_funcs->glyph_format; + FT_Raster_Funcs* funcs; + FT_Raster raster; + FT_Error error; + FT_Int n, index; + + if ( glyph_format == ft_glyph_format_none) + return FT_Err_Invalid_Argument; + + /* create a new raster object */ + error = raster_funcs->raster_new( library->memory, &raster ); + if (error) goto Exit; + + raster_funcs->raster_reset( raster, + library->raster_pool, + library->raster_pool_size ); + + index = -1; + for (n = 0; n < FT_MAX_GLYPH_FORMATS; n++) { - error = FT_Err_Invalid_Argument; - goto Exit; - } + FT_Raster_Funcs* funcs = library->raster_funcs + n; - /* free previous raster object if necessary */ - if ( format->raster_allocated ) - { - FREE( format->raster ); - format->raster_allocated = 0; - } - - /* allocate new raster object is necessary */ - if ( !raster ) - { - if ( ALLOC( raster, interface->size ) ) - goto Exit; - - format->raster_allocated = 1; - } - format->raster = raster; - format->raster_interface = interface; - - /* initialize the raster object */ - error = interface->init( raster, - (char*)library->raster_pool, - FT_RENDER_POOL_SIZE ); - if ( error ) - { - if ( format->raster_allocated ) + /* record the first vacant entry in "index" */ + if (index < 0 && funcs->glyph_format == ft_glyph_format_none) + index = n; + + /* compare this entry's glyph format with the one we need */ + if (funcs->glyph_format == glyph_format) { - FREE( format->raster ); - format->raster_allocated = 0; + /* a raster already exists for this glyph format, we will */ + /* destroy it before updating its entry in the table */ + funcs->raster_done( library->rasters[n] ); + index = n; + break; + } + } + + if (index < 0) + { + /* the table is full and has no vacant entries */ + error = FT_Err_Too_Many_Glyph_Formats; + goto Fail; + } + + funcs = library->raster_funcs + index; + *funcs = *raster_funcs; + library->rasters[index] = raster; + + Exit: + return error; + + Fail: + raster_funcs->raster_done( raster ); + goto Exit; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Unset_Raster */ + /* */ + /* */ + /* Removes a given raster from the library. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* raster_funcs :: pointer to the raster's interface */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Unset_Raster( FT_Library library, + FT_Raster_Funcs* raster_funcs ) + { + FT_Glyph_Format glyph_format = raster_funcs->glyph_format; + FT_Error error; + FT_Int n; + + error = FT_Err_Invalid_Argument; + if ( glyph_format == ft_glyph_format_none) + goto Exit; + + for (n = 0; n < FT_MAX_GLYPH_FORMATS; n++) + { + FT_Raster_Funcs* funcs = library->raster_funcs + n; + + if (funcs->glyph_format == glyph_format) + { + funcs->raster_done( library->rasters[n] ); + library->rasters[n] = 0; + library->raster_funcs[n].glyph_format = ft_glyph_format_none; + error = FT_Err_Ok; + break; } } @@ -499,6 +569,38 @@ } + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Raster_Mode */ + /* */ + /* */ + /* Set a raster-specific mode. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* format :: the glyph format used to select the raster */ + /* mode :: the raster-specific mode descriptor */ + /* args :: the mode arguments */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Set_Raster_Mode( FT_Library library, + FT_Glyph_Format format, + const char* mode, + void* args ) + { + FT_Raster_Funcs funcs; + FT_Raster raster; + + raster = FT_Get_Raster( library, format, &funcs ); + if (raster && funcs.raster_set_mode ) + return funcs.raster_set_mode( raster, mode, args ); + else + return FT_Err_Invalid_Argument; + } + /*************************************************************************/ /* */ /* */ @@ -529,105 +631,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* FT_Add_Glyph_Format */ - /* */ - /* */ - /* Adds a glyph format to the library. */ - /* */ - /* */ - /* library :: A handle to the library object. */ - /* */ - /* */ - /* format :: A pointer to the new glyph format. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - BASE_FUNC - FT_Error FT_Add_Glyph_Format( FT_Library library, - FT_Glyph_Format* format ) - { - FT_Glyph_Format* new = 0; - - - { - FT_Glyph_Format* cur = library->glyph_formats; - FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; - - - for ( ; cur < limit; cur++ ) - { - /* return an error if the format is already registered */ - if ( cur->format_tag == format->format_tag ) - return FT_Err_Invalid_Glyph_Format; - - if ( cur->format_tag == 0 && new == 0 ) - new = cur; - } - } - - /* if there is no place to hold the new format, return an error */ - if ( !new ) - return FT_Err_Too_Many_Glyph_Formats; - - *new = *format; - - /* now, create a raster object if we need to */ - return FT_Set_Raster( library, - format->raster_interface, - format->raster ); - } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Remove_Glyph_Format */ - /* */ - /* */ - /* Removes a glyph format from the library. */ - /* */ - /* */ - /* library :: A handle to the library object. */ - /* */ - /* */ - /* format_tag :: A tag identifying the format to be removed. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - BASE_FUNC - FT_Error FT_Remove_Glyph_Format( FT_Library library, - FT_Glyph_Tag format_tag ) - { - FT_Memory memory; - FT_Glyph_Format* cur = library->glyph_formats; - FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; - - - memory = library->memory; - - for ( ; cur < limit; cur++ ) - { - if ( cur->format_tag == format_tag ) - { - if ( cur->raster_allocated ) - { - FREE( cur->raster ); - cur->raster_allocated = 0; - } - cur->format_tag = 0; - return FT_Err_Ok; - } - } - - return FT_Err_Invalid_Argument; - } - - /*************************************************************************/ /* */ /* */ @@ -654,31 +657,29 @@ FT_Library library = 0; FT_Error error; - /* first of all, allocate the library object */ if ( ALLOC( library, sizeof ( *library ) ) ) return error; library->memory = memory; + /* allocate the render pool */ + library->raster_pool_size = FT_RENDER_POOL_SIZE; + if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) + goto Fail; + /* now register the default raster for the `outline' glyph image format */ - { - FT_Glyph_Format outline_format = - { - ft_glyph_format_outline, - &ft_default_raster, - 0, - 0 - }; - - - error = FT_Add_Glyph_Format( library, &outline_format ); - } + /* for now, ignore the error... */ + error = FT_Set_Raster( library, &ft_default_raster ); + /* That's ok now */ *alibrary = library; return FT_Err_Ok; + Fail: + FREE( library ); + return error; } @@ -726,20 +727,22 @@ } } - /* Destroy raster object */ + /* Destroy raster objects */ FREE( library->raster_pool ); + library->raster_pool_size = 0; { - FT_Glyph_Format* cur = library->glyph_formats; - FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + FT_Raster_Funcs* cur = library->raster_funcs; + FT_Raster_Funcs* limit = cur + FT_MAX_GLYPH_FORMATS; + FT_Raster* raster = library->rasters; - - for ( ; cur < limit; cur++ ) + for ( ; cur < limit; cur++, raster++ ) { - if ( cur->raster_allocated ) + if ( cur->glyph_format != ft_glyph_format_none ) { - FREE( cur->raster ); - cur->raster_allocated = 0; + cur->raster_done( *raster ); + *raster = 0; + cur->glyph_format = ft_glyph_format_none; } } } @@ -750,65 +753,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* FT_Set_Raster_Mode */ - /* */ - /* */ - /* Sets a raster-specific mode. */ - /* */ - /* */ - /* library :: A handle to a target library object. */ - /* */ - /* */ - /* format :: The glyph format used to select the raster. */ - /* mode :: The raster-specific mode descriptor. */ - /* args :: The mode arguments. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - EXPORT_FUNC - FT_Error FT_Set_Raster_Mode( FT_Library library, - FT_Glyph_Tag format_tag, - const char* mode, - const char* args ) - { - FT_Memory memory; - FT_Error error; - FT_Glyph_Format* format = 0; - - - { - FT_Glyph_Format* cur = library->glyph_formats; - FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; - - - for ( ; cur < limit; cur++ ) - { - if ( cur->format_tag == format_tag ) - { - format = cur; - break; - } - } - } - - if ( !format ) - return FT_Err_Invalid_Argument; - - memory = library->memory; - - error = FT_Err_Ok; - if ( format->raster ) - error = format->raster_interface->set_mode( format->raster, - mode, args ); - - return error; - } - - /*************************************************************************/ /* */ /* */ @@ -1028,10 +972,6 @@ } - static - const FT_Open_Args ft_default_open_args = - { 0, 0, 0, 0, 0 }; - /*************************************************************************/ /* */ @@ -1076,10 +1016,11 @@ FT_Long face_index, FT_Face* aface ) { - FT_Open_Args args = ft_default_open_args; + FT_Open_Args args; - - args.pathname = (char*)pathname; + args.stream_type = ft_stream_pathname; + args.driver = 0; + args.pathname = (char*)pathname; return FT_Open_Face( library, &args, face_index, aface ); } @@ -1129,11 +1070,12 @@ FT_Long face_index, FT_Face* face ) { - FT_Open_Args args = ft_default_open_args; - + FT_Open_Args args; + args.stream_type = ft_stream_memory; args.memory_base = file_base; args.memory_size = file_size; + args.driver = 0; return FT_Open_Face( library, &args, face_index, face ); } @@ -1198,8 +1140,7 @@ /* create input stream */ error = ft_new_input_stream( library, args, &stream ); - if ( error ) - goto Exit; + if ( error ) goto Exit; memory = library->memory; @@ -1281,6 +1222,15 @@ goto Fail; } + /* initialize transform for convenience functions */ + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + + face->transform_delta.x = 0; + face->transform_delta.y = 0; + *aface = face; goto Exit; @@ -1329,9 +1279,10 @@ FT_Error FT_Attach_File( FT_Face face, const char* filepathname ) { - FT_Open_Args open = ft_default_open_args; + FT_Open_Args open; - open.pathname = (char*)filepathname; + open.stream_type = ft_stream_pathname; + open.pathname = (char*)filepathname; return FT_Attach_Stream( face, &open ); } @@ -1875,6 +1826,10 @@ return FT_Err_Invalid_Face_Handle; driver = face->driver; + + /* when the flag NO_RECURSE is set, we disable hinting and scaling */ + if (load_flags & FT_LOAD_NO_RECURSE) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; error = driver->interface.load_glyph( face->glyph, face->size, @@ -2008,615 +1963,6 @@ return result; } - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Decompose */ - /* */ - /* */ - /* Walks over an outline's structure to decompose it into individual */ - /* segments and Bezier arcs. This function is also able to emit */ - /* `move to' and `close to' operations to indicate the start and end */ - /* of new contours in the outline. */ - /* */ - /* */ - /* outline :: A pointer to the source target. */ - /* */ - /* interface :: A table of `emitters', i.e,. function pointers called */ - /* during decomposition to indicate path operations. */ - /* */ - /* user :: A typeless pointer which is passed to each emitter */ - /* during the decomposition. It can be used to store */ - /* the state during the decomposition. */ - /* */ - /* */ - /* Error code. 0 means sucess. */ - /* */ - EXPORT_FUNC - int FT_Outline_Decompose( FT_Outline* outline, - FT_Outline_Funcs* interface, - void* user ) - { - typedef enum _phases - { - phase_point, - phase_conic, - phase_cubic, - phase_cubic2 - - } TPhase; - - FT_Vector v_first; - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_control2; - FT_Vector v_start; - - FT_Vector* point; - char* tags; - - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - int index; /* current point's index */ - - int error; - - char tag; /* current point's state */ - TPhase phase; - - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - - last = outline->contours[n]; - - v_first = outline->points[first]; - v_last = outline->points[last]; - - v_start = v_control = v_first; - - tag = FT_CURVE_TAG( outline->tags[first] ); - index = first; - - /* A contour cannot start with a cubic control point! */ - - if ( tag == FT_Curve_Tag_Cubic ) - return FT_Err_Invalid_Outline; - - - /* 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; - } - 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; - } - phase = phase_conic; - } - else - phase = phase_point; - - - /* Begin a new contour with MOVE_TO */ - - error = interface->move_to( &v_start, user ); - if ( error ) - return error; - - point = outline->points + first; - tags = outline->tags + first; - - /* now process each contour point individually */ - - while ( index < last ) - { - index++; - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - - switch ( phase ) - { - case phase_point: /* the previous point was on the curve */ - - switch ( tag ) - { - /* two succesive on points -> emit segment */ - case FT_Curve_Tag_On: - error = interface->line_to( point, user ); - break; - - /* on point + conic control -> remember control point */ - case FT_Curve_Tag_Conic: - v_control = point[0]; - phase = phase_conic; - break; - - /* on point + cubic control -> remember first control */ - default: - v_control = point[0]; - phase = phase_cubic; - break; - } - break; - - case phase_conic: /* the previous point was a conic control */ - - switch ( tag ) - { - /* conic control + on point -> emit conic arc */ - case FT_Curve_Tag_On: - error = interface->conic_to( &v_control, point, user ); - phase = phase_point; - break; - - /* two successive conics -> emit conic arc `in between' */ - case FT_Curve_Tag_Conic: - { - FT_Vector v_middle; - - - v_middle.x = (v_control.x + point->x)/2; - v_middle.y = (v_control.y + point->y)/2; - - error = interface->conic_to( &v_control, - &v_middle, user ); - v_control = point[0]; - } - break; - - default: - error = FT_Err_Invalid_Outline; - } - break; - - case phase_cubic: /* the previous point was a cubic control */ - - /* this point _must_ be a cubic control too */ - if ( tag != FT_Curve_Tag_Cubic ) - return FT_Err_Invalid_Outline; - - v_control2 = point[0]; - phase = phase_cubic2; - break; - - - case phase_cubic2: /* the two previous points were cubics */ - - /* this point _must_ be an on point */ - if ( tag != FT_Curve_Tag_On ) - error = FT_Err_Invalid_Outline; - else - error = interface->cubic_to( &v_control, &v_control2, - point, user ); - phase = phase_point; - break; - } - - /* lazy error testing */ - if ( error ) - return error; - } - - /* end of contour, close curve cleanly */ - error = 0; - - tag = FT_CURVE_TAG( outline->tags[first] ); - - switch ( phase ) - { - case phase_point: - if ( tag == FT_Curve_Tag_On ) - error = interface->line_to( &v_first, user ); - break; - - case phase_conic: - error = interface->conic_to( &v_control, &v_start, user ); - break; - - case phase_cubic2: - if ( tag == FT_Curve_Tag_On ) - error = interface->cubic_to( &v_control, &v_control2, - &v_first, user ); - else - error = FT_Err_Invalid_Outline; - break; - - default: - error = FT_Err_Invalid_Outline; - break; - } - - if ( error ) - return error; - - first = last + 1; - } - - return 0; - } - - - static - const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_New */ - /* */ - /* */ - /* Creates a new outline of a given size. */ - /* */ - /* */ - /* library :: A handle to the library object from where the */ - /* outline is allocated. Note however that the new */ - /* outline will NOT necessarily be FREED when */ - /* destroying the library, by FT_Done_FreeType(). */ - /* */ - /* numPoints :: The maximum number of points within the outline. */ - /* */ - /* numContours :: The maximum number of contours within the outline. */ - /* */ - /* */ - /* outline :: A handle to the new outline. NULL in case of */ - /* error. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* No. */ - /* */ - /* */ - /* The reason why this function takes a `library' parameter is simply */ - /* to use the library's memory allocator. You can copy the source */ - /* code of this function, replacing allocations with `malloc()' if */ - /* you want to control where the objects go. */ - /* */ - BASE_FUNC - FT_Error FT_Outline_New( FT_Library library, - FT_UInt numPoints, - FT_Int numContours, - FT_Outline* outline ) - { - FT_Error error; - FT_Memory memory; - - - if ( !outline ) - return FT_Err_Invalid_Argument; - - *outline = null_outline; - memory = library->memory; - - if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || - ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) || - ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) ) - goto Fail; - - outline->n_points = (FT_UShort)numPoints; - outline->n_contours = (FT_Short)numContours; - outline->flags |= ft_outline_owner; - - return FT_Err_Ok; - - Fail: - outline->flags |= ft_outline_owner; - FT_Outline_Done( library, outline ); - - return error; - } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Done */ - /* */ - /* */ - /* Destroys an outline created with FT_Outline_New(). */ - /* */ - /* */ - /* library :: A handle of the library object used to allocate the */ - /* outline. */ - /* */ - /* outline :: A pointer to the outline object to be discarded. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* No. */ - /* */ - /* */ - /* If the outline's `owner' field is not set, only the outline */ - /* descriptor will be released. */ - /* */ - /* The reason why this function takes an `outline' parameter is */ - /* simply to use FT_Alloc()/FT_Free(). You can copy the source code */ - /* of this function, replacing allocations with `malloc()' in your */ - /* application if you want something simpler. */ - /* */ - BASE_FUNC - FT_Error FT_Outline_Done( FT_Library library, - FT_Outline* outline ) - { - FT_Memory memory = library->memory; - - - if ( outline ) - { - if ( outline->flags & ft_outline_owner ) - { - FREE( outline->points ); - FREE( outline->tags ); - FREE( outline->contours ); - } - *outline = null_outline; - - return FT_Err_Ok; - } - else - return FT_Err_Invalid_Argument; - } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Get_CBox */ - /* */ - /* */ - /* Returns an outline's `control box'. The control box encloses all */ - /* the outline's points, including Bezier control points. Though it */ - /* coincides with the exact bounding box for most glyphs, it can be */ - /* slightly larger in some situations (like when rotating an outline */ - /* which contains Bezier outside arcs). */ - /* */ - /* Computing the control box is very fast, while getting the bounding */ - /* box can take much more time as it needs to walk over all segments */ - /* and arcs in the outline. To get the latter, you can use the */ - /* `ftbbox' component which is dedicated to this single task. */ - /* */ - /* */ - /* outline :: A pointer to the source outline descriptor. */ - /* */ - /* */ - /* cbox :: The outline's control box. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* Yes. */ - /* */ - BASE_FUNC - FT_Error FT_Outline_Get_CBox( FT_Outline* outline, - FT_BBox* cbox ) - { - FT_Pos xMin, yMin, xMax, yMax; - - if ( outline && cbox ) - { - if ( outline->n_points == 0 ) - { - xMin = 0; - yMin = 0; - xMax = 0; - yMax = 0; - } - else - { - FT_Vector* vec = outline->points; - FT_Vector* limit = vec + outline->n_points; - - xMin = xMax = vec->x; - yMin = yMax = vec->y; - vec++; - - for ( ; vec < limit; vec++ ) - { - FT_Pos x, y; - - x = vec->x; - if ( x < xMin ) xMin = x; - if ( x > xMax ) xMax = x; - - y = vec->y; - if ( y < yMin ) yMin = y; - if ( y > yMax ) yMax = y; - } - } - cbox->xMin = xMin; - cbox->xMax = xMax; - cbox->yMin = yMin; - cbox->yMax = yMax; - return FT_Err_Ok; - } - else - return FT_Err_Invalid_Argument; - } - - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Translate */ - /* */ - /* */ - /* Applies a simple translation to the points of an outline. */ - /* */ - /* */ - /* outline :: A pointer to the target outline descriptor. */ - /* xOffset :: The horizontal offset. */ - /* yOffset :: The vertical offset. */ - /* */ - /* */ - /* Yes. */ - /* */ - BASE_FUNC - void FT_Outline_Translate( FT_Outline* outline, - FT_Pos xOffset, - FT_Pos yOffset ) - { - FT_UShort n; - FT_Vector* vec = outline->points; - - for ( n = 0; n < outline->n_points; n++ ) - { - vec->x += xOffset; - vec->y += yOffset; - vec++; - } - } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Done_GlyphZone */ - /* */ - /* */ - /* Deallocates a glyph zone. */ - /* */ - /* */ - /* zone :: pointer to the target glyph zone. */ - /* */ - BASE_FUNC - void FT_Done_GlyphZone( FT_GlyphZone* zone ) - { - FT_Memory memory = zone->memory; - - FREE( zone->contours ); - FREE( zone->tags ); - FREE( zone->cur ); - FREE( zone->org ); - - zone->max_points = zone->n_points = 0; - zone->max_contours = zone->n_contours = 0; - } - - /*************************************************************************/ - /* */ - /* */ - /* FT_New_GlyphZone */ - /* */ - /* */ - /* Allocates a new glyph zone. */ - /* */ - /* */ - /* memory :: A handle to the current memory object. */ - /* */ - /* maxPoints :: The capacity of glyph zone in points. */ - /* */ - /* maxContours :: The capacity of glyph zone in contours. */ - /* */ - /* */ - /* zone :: A pointer to the target glyph zone record. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - BASE_FUNC - FT_Error FT_New_GlyphZone( FT_Memory memory, - FT_UShort maxPoints, - FT_Short maxContours, - FT_GlyphZone* zone ) - { - FT_Error error; - - if (maxPoints > 0) - maxPoints += 2; - - MEM_Set( zone, 0, sizeof(*zone) ); - zone->memory = memory; - - if ( ALLOC_ARRAY( zone->org, maxPoints*2, FT_F26Dot6 ) || - ALLOC_ARRAY( zone->cur, maxPoints*2, FT_F26Dot6 ) || - ALLOC_ARRAY( zone->tags, maxPoints, FT_Byte ) || - ALLOC_ARRAY( zone->contours, maxContours, FT_UShort ) ) - { - FT_Done_GlyphZone(zone); - } - return error; - } - - /*************************************************************************/ - /* */ - /* */ - /* FT_Update_GlyphZone */ - /* */ - /* */ - /* Checks the size of a zone and reallocates it if necessary. */ - /* */ - /* */ - /* newPoints :: The new capacity for points. We add two slots for */ - /* phantom points. */ - /* */ - /* newContours :: The new capacity for contours. */ - /* */ - /* */ - /* zone :: The address of the target zone. */ - /* */ - /* maxPoints :: The address of the zone's current capacity for */ - /* points. */ - /* */ - /* maxContours :: The address of the zone's current capacity for */ - /* contours. */ - /* */ - BASE_FUNC - FT_Error FT_Update_GlyphZone( FT_GlyphZone* zone, - FT_UShort newPoints, - FT_Short newContours ) - { - FT_Error error = FT_Err_Ok; - FT_Memory memory = zone->memory; - - newPoints += 2; - if ( zone->max_points < newPoints ) - { - /* reallocate the points arrays */ - if ( REALLOC_ARRAY( zone->org, zone->max_points*2, newPoints*2, FT_F26Dot6 ) || - REALLOC_ARRAY( zone->cur, zone->max_points*2, newPoints*2, FT_F26Dot6 ) || - REALLOC_ARRAY( zone->tags, zone->max_points*2, newPoints, FT_Byte ) ) - goto Exit; - - zone->max_points = newPoints; - } - - if ( zone->max_contours < newContours ) - { - /* reallocate the contours array */ - if ( REALLOC_ARRAY( zone->contours, zone->max_contours, newContours, FT_UShort ) ) - goto Exit; - - zone->max_contours = newContours; - } - Exit: - return error; - } - /*************************************************************************/ diff --git a/src/base/ftobjs.h b/src/base/ftobjs.h index f877963f7..158e07469 100644 --- a/src/base/ftobjs.h +++ b/src/base/ftobjs.h @@ -95,95 +95,17 @@ /*************************************************************************/ /*************************************************************************/ - /*************************************************************************/ - /* */ - /* */ - /* FT_Alloc */ - /* */ - /* */ - /* Allocates a new block of memory. The returned area is always */ - /* zero-filled, this is a strong convention in many FreeType parts. */ - /* */ - /* */ - /* memory :: A handle to a given `memory object' where allocation */ - /* occurs. */ - /* */ - /* size :: The size in bytes of the block to allocate. */ - /* */ - /* */ - /* P :: A pointer to the fresh new block. It should be set to */ - /* NULL if `size' is 0, or in case of error. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ BASE_DEF FT_Error FT_Alloc( FT_Memory memory, FT_Long size, void** P ); - - /*************************************************************************/ - /* */ - /* */ - /* FT_Realloc */ - /* */ - /* */ - /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */ - /* from the heap, possibly changing `*P'. */ - /* */ - /* */ - /* memory :: A handle to a given `memory object' where allocation */ - /* occurs. */ - /* */ - /* current :: current block size in bytes */ - /* size :: the new block size in bytes */ - /* */ - /* */ - /* P :: A pointer to the fresh new block. It should be set to */ - /* NULL if `size' is 0, or in case of error. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* All callers of FT_Realloc _must_ provide the current block size */ - /* as well as the new one. */ - /* */ - /* When the memory object's flag FT_memory_FLAG_NO_REALLOC is */ - /* set, this function will try to emulate a realloc through uses */ - /* of FT_Alloc and FT_Free. Otherwise, it will call the memory- */ - /* specific "realloc" implementation. */ - /* */ - /* (Some embedded memorys do not have a working realloc). */ - /* */ BASE_DEF FT_Error FT_Realloc( FT_Memory memory, FT_Long current, FT_Long size, void** P ); - - /*************************************************************************/ - /* */ - /* */ - /* FT_Free */ - /* */ - /* */ - /* Releases a given block of memory allocated through FT_Alloc(). */ - /* */ - /* */ - /* memory :: A handle to a given `memory object' where allocation */ - /* occured. */ - /* */ - /* P :: This is the _address_ of a _pointer_ which points to the */ - /* allocated block. It is always set to NULL on exit. */ - /* */ - /* */ - /* If P or *P are NULL, this function should return successfully. */ - /* This is a strong convention within all of FreeType and its */ - /* drivers. */ - /* */ BASE_DEF void FT_Free( FT_Memory memory, void** P ); @@ -246,6 +168,23 @@ + EXPORT_DEF + FT_Error FT_New_Size( FT_Face face, + FT_Size* size ); + + EXPORT_DEF + FT_Error FT_Done_Size( FT_Size size ); + + EXPORT_DEF + FT_Error FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ); + + EXPORT_DEF + void FT_Done_GlyphSlot( FT_GlyphSlot slot ); + + + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -317,7 +256,17 @@ } FT_DriverRec; -#ifdef FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H Z O N E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ /************************************************************************ * @@ -357,6 +306,7 @@ } FT_GlyphZone; + BASE_DEF FT_Error FT_New_GlyphZone( FT_Memory memory, FT_UShort maxPoints, @@ -372,132 +322,6 @@ FT_Short num_contours ); - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** G L Y P H F O R M A T S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /************************************************************************* - * - * - * FT_Glyph_Format - * - * - * A structure used to model various properties of a non-standard - * glyph image format. - * - * - * format_tag :: the glyph format tag - * - * raster_interface :: the default rasters interface for this glyph - * format. - * - * raster :: the default raster object for this glyph format - * if set to nil, a new object will be allocated - * automatically through the raster interface. - * - * raster_owned :: a boolean used internally by the library. If - * set, if indicates that the current raster object - * was allocated by the library. - * - *************************************************************************/ - - typedef struct FT_Glyph_Format_ - { - FT_Glyph_Tag format_tag; - FT_Raster_Interface* raster_interface; - FT_Raster raster; - FT_Bool raster_allocated; - - } FT_Glyph_Format; - - - /************************************************************************* - * - * - * FT_Add_Glyph_Format - * - * - * Register a new glyph format into the library - * - * - * library :: handle to target library object - * interface :: pointer to glyph format interface - * - * - * Error code. 0 means success - * - * - * This function should normally be called by those font drivers which - * need to use their own glyph image format. - * - *************************************************************************/ - - EXPORT_DEF - FT_Error FT_Add_Glyph_Format( FT_Library library, - FT_Glyph_Format* format ); - - - /************************************************************************* - * - * - * FT_Remove_Glyph_Format - * - * - * Un-Register a given glyph format from the library - * - * - * library :: handle to target library object - * glyph_format :: glyph format tag - * - * - * Error code. 0 means success - * - * - * This function should normally be called by those font drivers which - * need to use their own glyph image format. - * - *************************************************************************/ - - EXPORT_DEF - FT_Error FT_Remove_Glyph_Format( FT_Library library, - FT_Glyph_Tag glyph_format ); - - /************************************************************************* - * - * - * FT_Get_Glyph_Format - * - * - * Return a pointer to the glyph format descriptor corresponding to - * a given format tag. - * - * - * library :: handle to source library object - * - * format_tag :: glyph format tag - * - * - * a pointer to the corresponding glyph format descriptor, if it was - * registered in the library. 0 otherwise. - * - *************************************************************************/ - - BASE_DEF - FT_Glyph_Format* FT_Get_Glyph_Format( FT_Library library, - FT_Glyph_Tag format_tag ); - - - -#endif /* FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS */ - /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -539,10 +363,6 @@ /* registered font drivers. Note that each driver */ /* contains a list of its opened faces. */ /* */ - /* glyph_formats :: A table used to store glyph format descriptors */ - /* for new image formats that may have been */ - /* registered within the library */ - /* */ /* raster_pool :: The raster object's render pool. This can */ /* ideally be changed dynamically at run-time. */ /* */ @@ -557,59 +377,22 @@ FT_Int num_drivers; FT_Driver drivers[ FT_MAX_DRIVERS ]; /* driver objects */ - FT_Glyph_Format glyph_formats[FT_MAX_GLYPH_FORMATS]; + FT_Raster_Funcs raster_funcs[ FT_MAX_GLYPH_FORMATS ]; + FT_Raster rasters [ FT_MAX_GLYPH_FORMATS ]; - void* raster_pool; /* scan-line conversion render pool */ + void* raster_pool; /* scan-line conversion render pool */ + long raster_pool_size; /* size of render pool in bytes */ FT_DebugHook_Func debug_hooks[4]; } FT_LibraryRec; - /*************************************************************************/ - /* */ - /* */ - /* FT_New_Library */ - /* */ - /* */ - /* This function is used to create a new FreeType library instance */ - /* from a given memory object. It is thus possible to use libraries */ - /* with distinct memory allocators within the same program. */ - /* */ - /* */ - /* memory :: A handle to the original memory object. */ - /* */ - /* */ - /* library :: A handle to a new library object. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - /* */ - /* This function is normally not called by client applications, */ - /* unless they want to create a specific instance of FreeType which */ - /* uses a specific memory allocator. */ - /* */ EXPORT_DEF FT_Error FT_New_Library( FT_Memory memory, FT_Library* library ); - /*************************************************************************/ - /* */ - /* */ - /* FT_Done_Library */ - /* */ - /* */ - /* Discards a given library object. This closes all drivers and */ - /* discards all face objects. */ - /* */ - /* */ - /* library :: A handle to the target library. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ EXPORT_DEF FT_Error FT_Done_Library( FT_Library library ); @@ -621,127 +404,26 @@ FT_DebugHook_Func debug_hook ); - /*************************************************************************/ - /* */ - /* */ - /* FT_Add_Driver */ - /* */ - /* */ - /* Registers a new driver in a given library object. This function */ - /* takes only a pointer to a driver interface. It uses it to create */ - /* the new driver, then sets up some important fields. */ - /* */ - /* */ - /* library :: A handle to the target library object. */ - /* */ - /* driver_interface :: A pointer to a driver interface table. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - /* */ - /* This function doesn't check whether the driver is already */ - /* installed! */ - /* */ EXPORT_DEF FT_Error FT_Add_Driver( FT_Library library, const FT_DriverInterface* driver_interface ); - /*************************************************************************/ - /* */ - /* */ - /* FT_Remove_Driver */ - /* */ - /* */ - /* Unregister a given driver. This closes the driver, which in turn */ - /* destroys all faces, sizes, slots, etc. associated with it. */ - /* */ - /* This function also DESTROYS the driver object. */ - /* */ - /* */ - /* driver :: A handle to target driver object. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ EXPORT_DEF FT_Error FT_Remove_Driver( FT_Driver driver ); - /*************************************************************************/ - /* */ - /* */ - /* FT_Get_Driver */ - /* */ - /* */ - /* returns the handle of the driver responsible for a given format */ - /* (or service) according to its `name'. */ - /* */ - /* */ - /* library :: handle to library object. */ - /* driver_name :: name of driver to look-up. */ - /* */ - /* */ - /* handle to driver object. 0 otherwise */ - /* */ EXPORT_DEF FT_Driver FT_Get_Driver( FT_Library library, char* driver_name ); #ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM - /************************************************************************** - * - * - * FT_New_Stream - * - * - * Open a new stream from a given standard ASCII file path name - * - * - * filepathname :: an ASCII string naming the file to be opened - * - * - * astream :: the opened stream descriptor to be used by the library - * - * - * Error code. 0 means success - * - * - * This function must be implemented by the system-specific part - * of the engine, i.e. `ftsystem.c'. - * - * This function should only fill the stream descriptor. Note that - * the stream's `memory' field should be left to the caller. - * - **************************************************************************/ - extern FT_Error FT_New_Stream( const char* filepathname, FT_Stream astream ); - /************************************************************************** - * - * - * FT_New_Memory - * - * - * Returns a handle to a new memory object - * - * - * Handle to the memory object. 0 means failure - * - * - * This function must be implemented by the system-specific part - * of the engine, i.e. `ftsystem.c'. - * - * It is only used by `ftinit' in order to implement the function - * FT_Init_FreeType. - * - **************************************************************************/ - extern FT_Memory FT_New_Memory( void ); @@ -753,7 +435,7 @@ /* */ #ifndef FT_NO_DEFAULT_RASTER extern - FT_Raster_Interface ft_default_raster; + FT_Raster_Funcs ft_default_raster; #endif diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 0253aba92..43ec6dbea 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -29,6 +29,740 @@ #include #include + static + const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* */ + /* outline :: A pointer to the source target. */ + /* */ + /* interface :: A table of `emitters', i.e,. function pointers called */ + /* during decomposition to indicate path operations. */ + /* */ + /* user :: A typeless pointer which is passed to each emitter */ + /* during the decomposition. It can be used to store */ + /* the state during the decomposition. */ + /* */ + /* */ + /* Error code. 0 means sucess. */ + /* */ + EXPORT_FUNC + int FT_Outline_Decompose( FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ) + { + typedef enum _phases + { + phase_point, + phase_conic, + phase_cubic, + phase_cubic2 + + } TPhase; + + FT_Vector v_first; + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int error; + char tag; /* current point's state */ + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + int last; /* index of last point in contour */ + + last = outline->contours[n]; + limit = outline->points + last; + + v_first = outline->points[first]; + v_last = outline->points[last]; + + v_start = v_control = v_first; + + 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 ) + goto Invalid_Outline; + + /* 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--; + } + + error = interface->move_to( &v_start, user ); + if (error) goto Exit; + + while (point < limit) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch (tag) + { + case FT_Curve_Tag_On: /* emit a single line_to */ + { + error = interface->line_to( point, user ); + if (error) goto Exit; + continue; + } + + + case FT_Curve_Tag_Conic: /* consume conic arcs */ + { + v_control = point[0]; + + Do_Conic: + if (point < limit) + { + FT_Vector v_middle; + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + if (tag == FT_Curve_Tag_On) + { + error = interface->conic_to( &v_control, point, user ); + if (error) goto Exit; + continue; + } + + if (tag != FT_Curve_Tag_Conic) + goto Invalid_Outline; + + v_middle.x = (v_control.x + point->x)/2; + v_middle.y = (v_control.y + point->y)/2; + + error = interface->conic_to( &v_control, &v_middle, user ); + if (error) goto Exit; + + v_control = point[0]; + goto Do_Conic; + } + + error = interface->conic_to( &v_control, &v_start, user ); + goto Close; + } + + default: /* FT_Curve_Tag_Cubic */ + { + if ( point+1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + if (point <= limit) + { + error = interface->cubic_to( point-2, point-1, point, user ); + if (error) goto Exit; + continue; + } + + error = interface->cubic_to( point-2, point-1, &v_start, user ); + goto Close; + } + } + } + + /* close the contour with a line segment */ + error = interface->line_to( &v_start, user ); + + Close: + if (error) goto Exit; + first = last+1; + } + + return 0; + Exit: + return error; + + Invalid_Outline: + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will NOT necessarily be FREED when */ + /* destroying the library, by FT_Done_FreeType(). */ + /* */ + /* numPoints :: The maximum number of points within the outline. */ + /* */ + /* numContours :: The maximum number of contours within the outline. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. You can copy the source */ + /* code of this function, replacing allocations with `malloc()' if */ + /* you want to control where the objects go. */ + /* */ + BASE_FUNC + FT_Error FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + FT_Error error; + FT_Memory memory; + + + if ( !outline ) + return FT_Err_Invalid_Argument; + + *outline = null_outline; + memory = library->memory; + + if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || + ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) || + ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) ) + goto Fail; + + outline->n_points = (FT_UShort)numPoints; + outline->n_contours = (FT_Short)numContours; + outline->flags |= ft_outline_owner; + + return FT_Err_Ok; + + Fail: + outline->flags |= ft_outline_owner; + FT_Outline_Done( library, outline ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Alloc()/FT_Free(). You can copy the source code */ + /* of this function, replacing allocations with `malloc()' in your */ + /* application if you want something simpler. */ + /* */ + BASE_FUNC + FT_Error FT_Outline_Done( FT_Library library, + FT_Outline* outline ) + { + FT_Memory memory = library->memory; + + if ( outline ) + { + if ( outline->flags & ft_outline_owner ) + { + FREE( outline->points ); + FREE( outline->tags ); + FREE( outline->contours ); + } + *outline = null_outline; + + return FT_Err_Ok; + } + else + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* Returns an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + BASE_FUNC + void FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ) + { + FT_Pos xMin, yMin, xMax, yMax; + + if ( outline && cbox ) + { + if ( outline->n_points == 0 ) + { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + } + else + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + xMin = xMax = vec->x; + yMin = yMax = vec->y; + vec++; + + for ( ; vec < limit; vec++ ) + { + FT_Pos x, y; + + x = vec->x; + if ( x < xMin ) xMin = x; + if ( x > xMax ) xMax = x; + + y = vec->y; + if ( y < yMin ) yMin = y; + if ( y > yMax ) yMax = y; + } + } + cbox->xMin = xMin; + cbox->xMax = xMax; + cbox->yMin = yMin; + cbox->yMax = yMax; + } + } + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* xOffset :: The horizontal offset. */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + BASE_FUNC + void FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ) + { + FT_UShort n; + FT_Vector* vec = outline->points; + + for ( n = 0; n < outline->n_points; n++ ) + { + vec->x += xOffset; + vec->y += yOffset; + vec++; + } + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverse the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs.. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag ft_outline_reverse_fill in */ + /* the outline's "flags" field.. */ + /* */ + BASE_FUNC + void FT_Outline_Reverse( FT_Outline* outline ) + { + FT_UShort n; + FT_Int first, last; + + first = 0; + for ( n = 0; n < outline->n_contours; n++ ) + { + last = outline->contours[n]; + + /* reverse point table */ + { + FT_Vector* p = outline->points + first; + FT_Vector* q = outline->points + last; + FT_Vector swap; + + while (p < q) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + /* reverse tags table */ + { + char* p = outline->tags + first; + char* q = outline->tags + last; + char swap; + + while (p < q) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + first = last+1; + } + outline->flags ^= ft_outline_reverse_fill; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* zone :: pointer to the target glyph zone. */ + /* */ + BASE_FUNC + void FT_Done_GlyphZone( FT_GlyphZone* zone ) + { + FT_Memory memory = zone->memory; + + FREE( zone->contours ); + FREE( zone->tags ); + FREE( zone->cur ); + FREE( zone->org ); + + zone->max_points = zone->n_points = 0; + zone->max_contours = zone->n_contours = 0; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_GlyphZone */ + /* */ + /* */ + /* Allocates a new glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* maxPoints :: The capacity of glyph zone in points. */ + /* */ + /* maxContours :: The capacity of glyph zone in contours. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + BASE_FUNC + FT_Error FT_New_GlyphZone( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + FT_GlyphZone* zone ) + { + FT_Error error; + + if (maxPoints > 0) + maxPoints += 2; + + MEM_Set( zone, 0, sizeof(*zone) ); + zone->memory = memory; + + if ( ALLOC_ARRAY( zone->org, maxPoints*2, FT_F26Dot6 ) || + ALLOC_ARRAY( zone->cur, maxPoints*2, FT_F26Dot6 ) || + ALLOC_ARRAY( zone->tags, maxPoints, FT_Byte ) || + ALLOC_ARRAY( zone->contours, maxContours, FT_UShort ) ) + { + FT_Done_GlyphZone(zone); + } + return error; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Update_GlyphZone */ + /* */ + /* */ + /* Checks the size of a zone and reallocates it if necessary. */ + /* */ + /* */ + /* newPoints :: The new capacity for points. We add two slots for */ + /* phantom points. */ + /* */ + /* newContours :: The new capacity for contours. */ + /* */ + /* */ + /* zone :: The address of the target zone. */ + /* */ + /* maxPoints :: The address of the zone's current capacity for */ + /* points. */ + /* */ + /* maxContours :: The address of the zone's current capacity for */ + /* contours. */ + /* */ + BASE_FUNC + FT_Error FT_Update_GlyphZone( FT_GlyphZone* zone, + FT_UShort newPoints, + FT_Short newContours ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = zone->memory; + + newPoints += 2; + if ( zone->max_points < newPoints ) + { + /* reallocate the points arrays */ + if ( REALLOC_ARRAY( zone->org, zone->max_points*2, newPoints*2, FT_F26Dot6 ) || + REALLOC_ARRAY( zone->cur, zone->max_points*2, newPoints*2, FT_F26Dot6 ) || + REALLOC_ARRAY( zone->tags, zone->max_points*2, newPoints, FT_Byte ) ) + goto Exit; + + zone->max_points = newPoints; + } + + if ( zone->max_contours < newContours ) + { + /* reallocate the contours array */ + if ( REALLOC_ARRAY( zone->contours, zone->max_contours, newContours, FT_UShort ) ) + goto Exit; + + zone->max_contours = newContours; + } + Exit: + return error; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* or-ed to the target bitmap. */ + /* */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* outline :: A pointer to the source outline descriptor. */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + EXPORT_FUNC + FT_Error FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* map ) + { + FT_Error error; + FT_Raster raster; + FT_Raster_Funcs funcs; + FT_Raster_Params params; + + error = FT_Err_Invalid_Glyph_Format; + raster = FT_Get_Raster( library, ft_glyph_format_outline, &funcs ); + if (!raster) goto Exit; + + params.target = map; + params.source = outline; + params.flags = 0; + if (map->pixel_mode == ft_pixel_mode_grays) + params.flags |= ft_raster_flag_aa; + + error = funcs.raster_render( raster, ¶ms ); + Exit: + return error; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* Renders an outline within a bitmap using the current scan-convert */ + /* This functions uses a FT_Raster_Params as argument, allowing */ + /* advanced features like direct composition/translucency, etc.. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* outline :: A pointer to the source outline descriptor. */ + /* params :: A pointer to a FT_Raster_Params used to describe */ + /* the rendering operation */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* You should know what you're doing and the role of FT_Raster_Params */ + /* to use this function. */ + /* */ + /* the field "params.source" will be set to "outline" before the */ + /* scan converter is called, which means that the value you give it */ + /* is actually ignored.. */ + /* */ + EXPORT_FUNC + FT_Error FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ) + { + FT_Error error; + FT_Raster raster; + FT_Raster_Funcs funcs; + + error = FT_Err_Invalid_Glyph_Format; + raster = FT_Get_Raster( library, ft_glyph_format_outline, &funcs ); + if (!raster) goto Exit; + + params->source = (void*)outline; + error = funcs.raster_render( raster, params ); + Exit: + return error; + } + + + + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** The following functions are not used by the font drivers ****/ + /**** but they are provided as a convenience for client apps. ****/ + /**** ****/ + /**** Note that they will not be compiled if the configuration ****/ + /**** macro FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS is defined ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + +#ifndef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS + /*************************************************************************/ /* */ /* */ @@ -76,55 +810,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Get_Bitmap */ - /* */ - /* */ - /* Renders an outline within a bitmap. The outline's image is simply */ - /* or-ed to the target bitmap. */ - /* */ - /* */ - /* */ - /* library :: A handle to a FreeType library object. */ - /* outline :: A pointer to the source outline descriptor. */ - /* map :: A pointer to the target bitmap descriptor. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* YES. Rendering is synchronized, so that concurrent calls to the */ - /* scan-line converter will be serialized. */ - /* */ - /* */ - /* This function does NOT CREATE the bitmap, it only renders an */ - /* outline image within the one you pass to it! */ - /* */ - /* It will use the raster correponding to the default glyph format. */ - /* */ - BASE_FUNC - FT_Error FT_Outline_Get_Bitmap( FT_Library library, - FT_Outline* outline, - FT_Bitmap* map ) - { - FT_Error error; - FT_Glyph_Format* format; - - error = FT_Err_Invalid_Glyph_Format; - format = FT_Get_Glyph_Format( library, ft_glyph_format_outline ); - if (!format) goto Exit; - - error = FT_Err_Invalid_Glyph_Format; - if (!format->raster) goto Exit; - - error = format->raster_interface->render( format->raster, outline, map ); - Exit: - return error; - } - - /*************************************************************************/ /* */ /* */ @@ -158,7 +843,6 @@ { FT_Pos x, y; - x = FT_MulFix( vec->x, matrix->xx ) + FT_MulFix( vec->y, matrix->xy ); @@ -181,8 +865,7 @@ /* Transforms a single vector through a 2x2 matrix. */ /* */ /* */ - /* x :: The horizontal vector coordinate. */ - /* y :: The vertical vector coordinate. */ + /* vector :: The target vector to transform */ /* */ /* */ /* matrix :: A pointer to the source 2x2 matrix. */ @@ -190,22 +873,20 @@ /* */ /* Yes. */ /* */ - BASE_FUNC - void FT_Vector_Transform( FT_Pos* x, - FT_Pos* y, + EXPORT_DEF + void FT_Vector_Transform( FT_Vector* vector, FT_Matrix* matrix ) { FT_Pos xz, yz; + xz = FT_MulFix( vector->x, matrix->xx ) + + FT_MulFix( vector->y, matrix->xy ); - xz = FT_MulFix( *x, matrix->xx ) + - FT_MulFix( *y, matrix->xy ); + yz = FT_MulFix( vector->x, matrix->yx ) + + FT_MulFix( vector->y, matrix->yy ); - yz = FT_MulFix( *x, matrix->yx ) + - FT_MulFix( *y, matrix->yy ); - - *x = xz; - *y = yz; + vector->x = xz; + vector->y = yz; } @@ -286,5 +967,6 @@ return FT_Err_Ok; } +#endif /* END */ diff --git a/src/base/ftoutln.h b/src/base/ftoutln.h index 07b0b558b..438d00b2c 100644 --- a/src/base/ftoutln.h +++ b/src/base/ftoutln.h @@ -3,151 +3,4 @@ #include - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Copy */ - /* */ - /* */ - /* Copies an outline into another one. Both objects must have the */ - /* same sizes (number of points & number of contours) when this */ - /* function is called. */ - /* */ - /* */ - /* source :: A handle to the source outline. */ - /* target :: A handle to the target outline. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - EXPORT_DEF - FT_Error FT_Outline_Copy( FT_Outline* source, - FT_Outline* target ); - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Get_Bitmap */ - /* */ - /* */ - /* Renders an outline within a bitmap. The outline's image is simply */ - /* or-ed to the target bitmap. */ - /* */ - /* */ - /* */ - /* library :: A handle to a FreeType library object. */ - /* outline :: A pointer to the source outline descriptor. */ - /* map :: A pointer to the target bitmap descriptor. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* YES. Rendering is synchronized, so that concurrent calls to the */ - /* scan-line converter will be serialized. */ - /* */ - /* */ - /* This function does NOT CREATE the bitmap, it only renders an */ - /* outline image within the one you pass to it! */ - /* */ - /* It will use the raster correponding to the default glyph format. */ - /* */ - EXPORT_DEF - FT_Error FT_Outline_Get_Bitmap( FT_Library library, - FT_Outline* outline, - FT_Bitmap* map ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Transform */ - /* */ - /* */ - /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ - /* for applying rotations, slanting, flipping, etc. */ - /* */ - /* */ - /* outline :: A pointer to the target outline descriptor. */ - /* matrix :: A pointer to the transformation matrix. */ - /* */ - /* */ - /* Yes. */ - /* */ - /* */ - /* You can use FT_Outline_Translate() if you need to translate the */ - /* outline's points. */ - /* */ - EXPORT_DEF - void FT_Outline_Transform( FT_Outline* outline, - FT_Matrix* matrix ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Vector_Transform */ - /* */ - /* */ - /* Transforms a single vector through a 2x2 matrix. */ - /* */ - /* */ - /* x :: The horizontal vector coordinate. */ - /* y :: The vertical vector coordinate. */ - /* */ - /* */ - /* matrix :: A pointer to the source 2x2 matrix. */ - /* */ - /* */ - /* Yes. */ - /* */ - EXPORT_DEF - void FT_Vector_Transform( FT_Pos* x, - FT_Pos* y, - FT_Matrix* matrix ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Matrix_Multiply */ - /* */ - /* */ - /* Performs the matrix operation `b = a*b'. */ - /* */ - /* */ - /* a :: A pointer to matrix `a'. */ - /* */ - /* */ - /* b :: A pointer to matrix `b'. */ - /* */ - /* */ - /* Yes. */ - /* */ - EXPORT_DEF - void FT_Matrix_Multiply( FT_Matrix* a, - FT_Matrix* b ); - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Matrix_Invert */ - /* */ - /* */ - /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ - /* */ - /* */ - /* matrix :: A pointer to the target matrix. Remains untouched in */ - /* case of error. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* Yes. */ - /* */ - EXPORT_DEF - FT_Error FT_Matrix_Invert( FT_Matrix* matrix ); - #endif /* FTOUTLN_H */ diff --git a/src/base/ftraster.c b/src/base/ftraster.c index 8b1067878..601a5f4c8 100644 --- a/src/base/ftraster.c +++ b/src/base/ftraster.c @@ -92,7 +92,7 @@ /* Define this configuration macro if you want to support */ /* anti-aliasing. */ /* */ -#define FT_RASTER_OPTION_ANTI_ALIAS +#undef FT_RASTER_OPTION_ANTI_ALIAS /*************************************************************************/ @@ -643,6 +643,7 @@ TDirection state; /* rendering state */ FT_Bitmap target; /* description of target bit/pixmap */ + void* memory; int trace_bit; /* current offset in target bitmap */ int trace_pix; /* current offset in target pixmap */ @@ -2204,260 +2205,6 @@ #endif /* FT_RASTER_CUBIC_BEZIERS */ -/********************************************************************/ -/* */ -/* The following function is compiled in the raster only when it is */ -/* compile as a stand-alone module.. */ - -/* It can, otherwise, be found in the FreeType base layer */ - -#ifdef _STANDALONE_ - /*************************************************************************/ - /* */ - /* */ - /* FT_Outline_Decompose */ - /* */ - /* */ - /* Walks over an outline's structure to decompose it into individual */ - /* segments and Bezier arcs. This function is also able to emit */ - /* `move to' and `close to' operations to indicate the start and end */ - /* of new contours in the outline. */ - /* */ - /* */ - /* outline :: A pointer to the source target. */ - /* */ - /* interface :: A table of `emitters', i.e,. function pointers called */ - /* during decomposition to indicate path operations. */ - /* */ - /* user :: A typeless pointer which is passed to each emitter */ - /* during the decomposition. It can be used to store */ - /* the state during the decomposition. */ - /* */ - /* */ - /* Error code. 0 means sucess. */ - /* */ - static - int FT_Outline_Decompose( FT_Outline* outline, - FT_Outline_Funcs* interface, - void* user ) - { - typedef enum _phases - { - phase_point, - phase_conic, - phase_cubic, - phase_cubic2 - - } TPhase; - - FT_Vector v_first; - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_control2; - FT_Vector v_start; - - FT_Vector* point; - char* flags; - - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - int index; /* current point's index */ - - int error; - - char tag; /* current point's state */ - TPhase phase; - - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - - last = outline->contours[n]; - - v_first = outline->points[first]; - v_last = outline->points[last]; - - v_start = v_control = v_first; - - tag = FT_CURVE_TAG( outline->flags[first] ); - index = first; - - /* A contour cannot start with a cubic control point! */ - - if ( tag == FT_Curve_Tag_Cubic ) - return ErrRaster_Invalid_Outline; - - - /* 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->flags[last] ) == FT_Curve_Tag_On ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - } - 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; - } - phase = phase_conic; - } - else - phase = phase_point; - - - /* Begin a new contour with MOVE_TO */ - - error = interface->move_to( &v_start, user ); - if ( error ) - return error; - - point = outline->points + first; - flags = outline->flags + first; - - /* now process each contour point individually */ - - while ( index < last ) - { - index++; - point++; - flags++; - - tag = FT_CURVE_TAG( flags[0] ); - - switch ( phase ) - { - case phase_point: /* the previous point was on the curve */ - - switch ( tag ) - { - /* two succesive on points -> emit segment */ - case FT_Curve_Tag_On: - error = interface->line_to( point, user ); - break; - - /* on point + conic control -> remember control point */ - case FT_Curve_Tag_Conic: - v_control = point[0]; - phase = phase_conic; - break; - - /* on point + cubic control -> remember first control */ - default: - v_control = point[0]; - phase = phase_cubic; - break; - } - break; - - case phase_conic: /* the previous point was a conic control */ - - switch ( tag ) - { - /* conic control + on point -> emit conic arc */ - case FT_Curve_Tag_On: - error = interface->conic_to( &v_control, point, user ); - phase = phase_point; - break; - - /* two successive conics -> emit conic arc `in between' */ - case FT_Curve_Tag_Conic: - { - FT_Vector v_middle; - - - v_middle.x = (v_control.x + point->x)/2; - v_middle.y = (v_control.y + point->y)/2; - - error = interface->conic_to( &v_control, - &v_middle, user ); - v_control = point[0]; - } - break; - - default: - error = ErrRaster_Invalid_Outline; - } - break; - - case phase_cubic: /* the previous point was a cubic control */ - - /* this point _must_ be a cubic control too */ - if ( tag != FT_Curve_Tag_Cubic ) - return ErrRaster_Invalid_Outline; - - v_control2 = point[0]; - phase = phase_cubic2; - break; - - - case phase_cubic2: /* the two previous points were cubics */ - - /* this point _must_ be an on point */ - if ( tag != FT_Curve_Tag_On ) - error = ErrRaster_Invalid_Outline; - else - error = interface->cubic_to( &v_control, &v_control2, - point, user ); - phase = phase_point; - break; - } - - /* lazy error testing */ - if ( error ) - return error; - } - - /* end of contour, close curve cleanly */ - error = 0; - - tag = FT_CURVE_TAG( outline->flags[first] ); - - switch ( phase ) - { - case phase_point: - if ( tag == FT_Curve_Tag_On ) - error = interface->line_to( &v_first, user ); - break; - - case phase_conic: - error = interface->conic_to( &v_control, &v_start, user ); - break; - - case phase_cubic2: - if ( tag == FT_Curve_Tag_On ) - error = interface->cubic_to( &v_control, &v_control2, - &v_first, user ); - else - error = ErrRaster_Invalid_Outline; - break; - - default: - error = ErrRaster_Invalid_Outline; - break; - } - - if ( error ) - return error; - - first = last + 1; - } - - return SUCCESS; - } -#endif /*************************************************************************/ /* */ @@ -3109,14 +2856,6 @@ x1 += PRECISION_HALF; x2 += PRECISION_HALF; -#ifdef FT_RASTER_OPTION_CONTRAST - if ( x2-x1 < PRECISION ) - { - x1 = ((x1+x2) >> 1) - PRECISION_HALF; - x2 = x1 + PRECISION; - } -#endif - e1 = TRUNC( x1 ); e2 = TRUNC( x2 ); @@ -3324,14 +3063,6 @@ x1 += PRECISION_HALF; x2 += PRECISION_HALF; -#ifdef FT_RASTER_OPTION_CONTRAST - if (x2-x1 < PRECISION) - { - x1 = ((x1+x2) >> 1) - PRECISION_HALF; - x2 = x1 + PRECISION; - } -#endif - e1 = TRUNC( x1 ); e2 = TRUNC( x2 ); @@ -4081,38 +3812,87 @@ Scan_DropOuts : #endif /* FT_RASTER_OPTION_ANTI_ALIAS */ - /*************************************************************************/ - /* */ - /* */ - /* FT_Raster_Render */ - /* */ - /* */ - /* Renders an outline into a target bitmap. */ - /* */ - /* */ - /* raster :: A handle to the raster object used during rendering. */ - /* outline :: A pointer to the source outline record/object. */ - /* bitmap :: A pointer to the target bitmap descriptor. */ - /* */ - /* */ - /* Error code, interpreted as a FT_Error by FreeType. 0 means */ - /* success. */ - /* */ - EXPORT_FUNC - int FT_Raster_Render( FT_Raster raster, - FT_Outline* outline, - FT_Bitmap* target_map ) + + /**** RASTER OBJECT CREATION : in standalone mode, we simply use *****/ + /**** a static object .. *****/ +#ifdef _STANDALONE_ + + static + int ft_raster_new( void* memory, FT_Raster *araster ) { + static FT_RasterRec_ the_raster; + *araster = &the_raster; + memset( &the_raster, sizeof(the_raster), 0 ); + return 0; + } + + static + void ft_raster_done( FT_Raster raster ) + { + /* nothing */ + raster->init = 0; + } + +#else + +#include "ftobjs.h" + + static + int ft_raster_new( FT_Memory memory, FT_Raster* araster ) + { + FT_Error error; + FT_Raster raster; + + *araster = 0; + if ( !ALLOC( raster, sizeof(*raster) )) + { + raster->memory = memory; + *araster = raster; + } + + return error; + } + + static + void ft_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)raster->memory; + FREE( raster ); + } + +#endif + + + static void ft_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + if ( raster && pool_base && pool_size >= 4096 ) + { + /* save the pool */ + raster->pool = (PPos)pool_base; + raster->pool_size = raster->pool + pool_size / sizeof ( TPos ); + } + } + + + static + int ft_raster_render( FT_Raster raster, + FT_Raster_Params* params ) + { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + if ( !raster || !raster->pool || !raster->pool_size ) return ErrRaster_Uninitialized_Object; + if ( !outline || !outline->contours || !outline->points ) + return ErrRaster_Invalid_Outline; + /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return ErrRaster_Ok; - if ( !outline || !outline->contours || !outline->points ) - return ErrRaster_Invalid_Outline; - if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) return ErrRaster_Invalid_Outline; @@ -4125,107 +3905,29 @@ Scan_DropOuts : /* Note that we always use drop-out mode 2, because it seems that */ /* it's the only way to do to get results consistent with Windows */ /* rendering.. */ -#if 0 - ras.dropout_mode = outline->dropout_mode; -#else ras.dropout_mode = 2; -#endif + ras.second_pass = (outline->flags & ft_outline_single_pass) == 0; SET_High_Precision( (char)((outline->flags & ft_outline_high_precision)!= 0) ); - switch ( target_map->pixel_mode ) - { - case ft_pixel_mode_mono: return Raster_Render1( raster ); - case ft_pixel_mode_grays: return Raster_Render8( raster ); - default: return ErrRaster_Unimplemented; - } + /* this version of the raster does not support direct rendering, sorry */ + if ( params->flags & ft_raster_flag_direct ) + return ErrRaster_Unimplemented; + + return ( params->flags & ft_raster_flag_aa + ? Raster_Render8( raster ) + : Raster_Render1( raster ) ); } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Raster_ObjSize */ - /* */ - /* */ - /* This function returns the size of a raster object in bytes. */ - /* Client applications are thus able to allocate objects in their own */ - /* heap/memory space, without revealing the internal structures of */ - /* the scan-line converter. */ - /* */ - /* */ - /* The size in bytes of a single raster object. */ - /* */ - EXPORT_FUNC - long FT_Raster_ObjSize( void ) + FT_Raster_Funcs ft_default_raster = { - return (long)sizeof( struct FT_RasterRec_ ); - } - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Raster_Init */ - /* */ - /* */ - /* Initializes a fresh raster object which should have been allocated */ - /* by client applications. This function is also used to set the */ - /* object's render pool. It can be used repeatedly on a single */ - /* object if one wants to change the pool's address or size. */ - /* */ - /* Note that the render pool has no state and is only used during a */ - /* call to FT_Raster_Render(). It is thus theorically possible to */ - /* share it between several non-concurrent components of your */ - /* applications when memory is a scarce resource. */ - /* */ - /* */ - /* pool_size :: The render pool's size in bytes. This must be at */ - /* least 4 kByte. */ - /* */ - /* */ - /* raster :: A handle to the target raster object. */ - /* */ - /* pool_base :: The render pool's base address in memory. */ - /* */ - /* */ - /* An error condition, used as a FT_Error in the FreeType library. */ - /* 0 means success. */ - /* */ - EXPORT_FUNC - int FT_Raster_Init( FT_Raster raster, - const char* pool_base, - long pool_size ) - { -/* static const char default_palette[5] = { 0, 1, 2, 3, 4 }; */ - - /* check the object address */ - if ( !raster ) - return ErrRaster_Uninitialized_Object; - - /* check the render pool - we won't go under 4 Kb */ - if ( !pool_base || pool_size < 4096 ) - return ErrRaster_Invalid_Pool; - - /* save the pool */ - raster->pool = (PPos)pool_base; - raster->pool_size = raster->pool + pool_size / sizeof ( TPos ); - - return ErrRaster_Ok; - } - - - - FT_Raster_Interface ft_default_raster = - { - sizeof( struct FT_RasterRec_ ), ft_glyph_format_outline, - - (FT_Raster_Init_Proc) FT_Raster_Init, - (FT_Raster_Set_Mode_Proc) 0, - (FT_Raster_Render_Proc) FT_Raster_Render + (FT_Raster_New_Func) ft_raster_new, + (FT_Raster_Reset_Func) ft_raster_reset, + (FT_Raster_Set_Mode_Func) 0, + (FT_Raster_Render_Func) ft_raster_render, + (FT_Raster_Done_Func) ft_raster_done }; diff --git a/src/base/rules.mk b/src/base/rules.mk index 0ad047928..30eb1ec18 100644 --- a/src/base/rules.mk +++ b/src/base/rules.mk @@ -33,7 +33,9 @@ BASE_SRC := $(BASE_)ftcalc.c \ $(BASE_)ftextend.c \ $(BASE_)ftlist.c \ $(BASE_)ftobjs.c \ - $(BASE_)ftstream.c + $(BASE_)ftstream.c \ + $(BASE_)ftoutln.c + # Base layer headers # @@ -53,7 +55,7 @@ BASE_H := $(BASE_)ftcalc.h \ # symbols is used by the application. # BASE_EXT_SRC := $(BASE_)ftraster.c \ - $(BASE_)ftoutln.c + $(BASE_)ftglyph.c # Base layer extensions headers #