=== include/freetype/ftbitmap.h ================================================================== --- include/freetype/ftbitmap.h (/freetype2/trunk) (revision 240) +++ include/freetype/ftbitmap.h (/freetype2/branches/embolden) (local) @@ -92,6 +92,42 @@ /*************************************************************************/ /* */ /* */ + /* FT_Bitmap_Embolden */ + /* */ + /* */ + /* Emboldens a bitmap. The new bitmap will be about xStrength */ + /* pixels wider and yStrength pixels higher. (The left and bottom */ + /* borders are kept unchanged) */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* */ + /* bitmap :: A handle to the target bitmap. */ + /* */ + /* xStrength :: How strong the glyph is emboldened horizontally. */ + /* Expressed in 16.16 pixel format. */ + /* */ + /* yStrength :: How strong the glyph is emboldened vertically. */ + /* Expressed in 16.16 pixel format. */ + /* */ + /* */ + /* FreeType error code */ + /* */ + /* */ + /* Current implementation restricts xStrength to be less than or */ + /* equal to 8. */ + /* */ + FT_EXPORT_DEF( FT_Error ) + FT_Bitmap_Embolden( FT_Library library, + FT_Bitmap* bitmap, + FT_Pos* xStrength, + FT_Pos* yStrength ); + + + /*************************************************************************/ + /* */ + /* */ /* FT_Bitmap_Convert */ /* */ /* */ === include/freetype/ftoutln.h ================================================================== --- include/freetype/ftoutln.h (/freetype2/trunk) (revision 240) +++ include/freetype/ftoutln.h (/freetype2/branches/embolden) (local) @@ -58,6 +58,7 @@ /* FT_Outline_Copy */ /* FT_Outline_Translate */ /* FT_Outline_Transform */ + /* FT_Outline_Embolden */ /* FT_Outline_Reverse */ /* FT_Outline_Check */ /* */ @@ -306,6 +307,33 @@ /*************************************************************************/ /* */ /* */ + /* FT_Outline_Embolden */ + /* */ + /* */ + /* Emboldens an outline. The new outline will be about xStrength */ + /* pixels wider and yStrength pixels higher. (The left and bottom */ + /* borders are kept unchanged) */ + /* */ + /* */ + /* outline :: A handle to the target outline. */ + /* */ + /* xStrength :: How strong the glyph is emboldened horizontally. */ + /* Expressed in 16.16 pixel format. */ + /* */ + /* yStrength :: How strong the glyph is emboldened vertically. */ + /* Expressed in 16.16 pixel format. */ + /* */ + /* */ + /* FreeType error code */ + /* */ + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Embolden( FT_Outline* outline, + FT_Pos* xStrength, + FT_Pos* yStrength ); + + /*************************************************************************/ + /* */ + /* */ /* FT_Outline_Reverse */ /* */ /* */ === src/base/ftbitmap.c ================================================================== --- src/base/ftbitmap.c (/freetype2/trunk) (revision 240) +++ src/base/ftbitmap.c (/freetype2/branches/embolden) (local) @@ -94,9 +94,194 @@ } + static FT_Error + ft_bitmap_assure_buffer( FT_Memory memory, + FT_Bitmap* bitmap, + FT_UInt xpixels, + FT_UInt ypixels ) + { + FT_Error error; + int pitch; + int new_pitch; + int ppb, i; + unsigned char* buffer; + + + pitch = bitmap->pitch; + if ( pitch < 0 ) + pitch = -pitch; + + switch ( bitmap->pixel_mode ) + { + case FT_PIXEL_MODE_MONO: + ppb = 8; + break; + case FT_PIXEL_MODE_GRAY2: + ppb = 4; + break; + case FT_PIXEL_MODE_GRAY4: + ppb = 2; + break; + case FT_PIXEL_MODE_GRAY: + ppb = 1; + break; + default: + return FT_Err_Invalid_Glyph_Format; + } + + /* no need to allocation */ + if ( ypixels == 0 && pitch * ppb >= bitmap->width + xpixels ) + return FT_Err_Ok; + + new_pitch = ( bitmap->width + xpixels + ppb - 1 ) / ppb; + + if ( FT_ALLOC( buffer, new_pitch * ( bitmap->rows + ypixels ) ) ) + return error; + + if ( bitmap->pitch > 0 ) + { + for ( i = 0; i < bitmap->rows; i++ ) + FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ), + bitmap->buffer + pitch * i, pitch ); + } + else + { + for ( i = 0; i < bitmap->rows; i++ ) + FT_MEM_COPY( buffer + new_pitch * i, + bitmap->buffer + pitch * i, pitch ); + } + + FT_FREE( bitmap->buffer ); + bitmap->buffer = buffer; + + if ( bitmap->pitch < 0 ) + new_pitch = -new_pitch; + + /* set pitch only */ + bitmap->pitch = new_pitch; + + return FT_Err_Ok; + } + + /* documentation is in ftbitmap.h */ FT_EXPORT_DEF( FT_Error ) + FT_Bitmap_Embolden( FT_Library library, + FT_Bitmap* bitmap, + FT_Pos* xStrength, + FT_Pos* yStrength ) + { + FT_Error error; + unsigned char* p; + int i, x, y, pitch; + FT_UInt xstr, ystr; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !bitmap || !xStrength || !yStrength ) + return FT_Err_Invalid_Argument; + + switch ( bitmap->pixel_mode ) + { + case FT_PIXEL_MODE_GRAY2: + case FT_PIXEL_MODE_GRAY4: + return FT_Err_Invalid_Glyph_Format; + } + + *xStrength = FT_PIX_ROUND( *xStrength ); + *yStrength = FT_PIX_ROUND( *yStrength ); + + xstr = *xStrength >> 6; + ystr = *yStrength >> 6; + + if ( xstr == 0 && ystr == 0 ) + return FT_Err_Ok; + else if ( xstr < 0 || ystr < 0 || xstr > 8 ) + return FT_Err_Invalid_Argument; + + error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr ); + if ( error ) + return error; + + pitch = bitmap->pitch; + if ( pitch > 0 ) + { + p = bitmap->buffer + pitch * ystr; + } + else + { + pitch = -pitch; + p = bitmap->buffer + pitch * ( bitmap->rows - ystr - 1 ); + } + + /* for each row */ + for ( y = 0; y < bitmap->rows ; y++ ) + { + /* + * Horizontally: + * + * From the last pixel on, make each pixel or'ed with the + * xstr pixels before it + */ + for ( x = pitch - 1; x >= 0; x-- ) + { + unsigned char tmp; + + tmp = p[x]; + for ( i = 1; i <= xstr; i++ ) + { + if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO ) + { + p[x] |= tmp >> i; + + /* the "8" restriction of xstr comes from here */ + if ( x > 0 ) + p[x] |= p[x - 1] << ( 8 - i ); + } + else if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY ) + { + if ( x - i >= 0 ) + { + if ( p[x] + p[x - i] > 0xff ) + p[x] = 0xff; + else + p[x] += p[x - i]; + } + } + } + } + + /* + * Vertically: + * + * make the above ystr rows or'ed with it + */ + for ( x = 1; x <= ystr; x++ ) + { + unsigned char* q; + + + q = p - bitmap->pitch * x; + for ( i = 0; i < pitch; i++ ) + q[i] |= p[i]; + } + + p += bitmap->pitch; + } + + bitmap->width += xstr; + bitmap->rows += ystr; + + return FT_Err_Ok; + } + + + /* documentation is in ftbitmap.h */ + + FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Convert( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target, === src/base/ftoutln.c ================================================================== --- src/base/ftoutln.c (/freetype2/trunk) (revision 240) +++ src/base/ftoutln.c (/freetype2/branches/embolden) (local) @@ -670,6 +670,114 @@ /* documentation is in ftoutln.h */ + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Embolden( FT_Outline* outline, + FT_Pos* xStrength, + FT_Pos* yStrength ) + { + FT_Vector* points; + FT_Vector v_prev, v_first, v_next, v_cur; + FT_Angle rotate, angle_in, angle_out; + FT_Int c, n, first; + + + if ( !outline || !xStrength || !yStrength ) + return FT_Err_Invalid_Argument; + + if ( *xStrength == 0 && *yStrength == 0 ) + return FT_Err_Ok; + + if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_TRUETYPE ) + rotate = -FT_ANGLE_PI2; + else + rotate = FT_ANGLE_PI2; + + points = outline->points; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + int last = outline->contours[c]; + + + v_first = points[first]; + v_prev = points[last]; + v_cur = v_first; + + for ( n = first; n <= last; n++ ) + { + FT_Vector in, out; + FT_Angle angle_diff; +#ifdef OLD_ALGORITHM + FT_Pos d; + FT_Fixed scale; +#endif + + + if ( n < last ) v_next = points[n + 1]; + else v_next = v_first; + + /* compute the in and out vectors */ + in.x = v_cur.x - v_prev.x; + in.y = v_cur.y - v_prev.y; + + out.x = v_next.x - v_cur.x; + out.y = v_next.y - v_cur.y; + + angle_in = FT_Atan2( in.x, in.y ); + angle_out = FT_Atan2( out.x, out.y ); + angle_diff = FT_Angle_Diff( angle_in, angle_out ); +#ifdef OLD_ALGORITHM + scale = FT_Cos( angle_diff / 2 ); + + if ( scale < 0x400L && scale > -0x400L ) + { + if ( scale >= 0 ) + scale = 0x400L; + else + scale = -0x400L; + } + + d = FT_DivFix( *xStrength, scale ); + + FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate ); + + outline->points[n].x = v_cur.x + strength + in.x; + outline->points[n].y = v_cur.y + strength + in.y; +#else + angle_diff = angle_in + angle_diff / 2 - rotate; + angle_diff = FT_Angle_Diff( 0, angle_diff ); + + if ( -FT_ANGLE_PI2 < angle_diff && angle_diff <= 0 ) { + outline->points[n].x = v_cur.x + *xStrength; + } + else if ( 0 < angle_diff && angle_diff < FT_ANGLE_PI2 ) { + outline->points[n].x = v_cur.x + *xStrength; + outline->points[n].y = v_cur.y + *yStrength; + } + else if ( FT_ANGLE_PI2 <= angle_diff && angle_diff < FT_ANGLE_PI ) { + outline->points[n].y = v_cur.y + *yStrength; + } +#endif + + v_prev = v_cur; + v_cur = v_next; + } + + first = last + 1; + } + +#ifdef OLD_ALGORITHM + /* *xStrength = ( *xStrength * 4 ) & ~63; */ + *yStrength = *xStrength; +#endif + + return FT_Err_Ok; + } + + + /* documentation is in ftoutln.h */ + FT_EXPORT_DEF( FT_Orientation ) FT_Outline_Get_Orientation( FT_Outline* outline ) { === src/base/ftsynth.c ================================================================== --- src/base/ftsynth.c (/freetype2/trunk) (revision 240) +++ src/base/ftsynth.c (/freetype2/branches/embolden) (local) @@ -17,11 +17,10 @@ #include +#include FT_SYNTHESIS_H #include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_CALC_H #include FT_OUTLINE_H -#include FT_TRIGONOMETRY_H -#include FT_SYNTHESIS_H +#include FT_BITMAP_H #define FT_BOLD_THRESHOLD 0x0100 @@ -77,87 +76,47 @@ FT_EXPORT_DEF( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) { - FT_Vector* points; - FT_Vector v_prev, v_first, v_next, v_cur; - FT_Pos distance; - FT_Outline* outline = &slot->outline; - FT_Face face = FT_SLOT_FACE( slot ); - FT_Angle rotate, angle_in, angle_out; - FT_Int c, n, first; + FT_Library library = slot->library; + FT_Face face = FT_SLOT_FACE( slot ); + FT_Pos xstr, ystr; + FT_Error error; - /* only embolden outline glyph images */ - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) - return; + /* some reasonable strength */ + xstr = FT_MulFix( face->units_per_EM, + face->size->metrics.y_scale ) / 32; + ystr = xstr; - /* compute control distance */ - distance = FT_MulFix( face->units_per_EM / 60, - face->size->metrics.y_scale ); + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) + { + error = FT_Outline_Embolden( &slot->outline, &xstr, &ystr ); + } + else if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) + { + xstr = FT_PIX_FLOOR( xstr ); + if ( xstr == 0 ) + xstr = 1 << 6; + ystr = FT_PIX_FLOOR( ystr ); - if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_TRUETYPE ) - rotate = -FT_ANGLE_PI2; + error = FT_Bitmap_Embolden( library, &slot->bitmap, &xstr, &ystr ); + + /* XXX should we set these? */ + if ( !error ) + slot->bitmap_top += ystr >> 6; + } else - rotate = FT_ANGLE_PI2; + error = FT_Err_Invalid_Argument; - points = outline->points; - - first = 0; - for ( c = 0; c < outline->n_contours; c++ ) + /* XXX should we set these? */ + if ( !error ) { - int last = outline->contours[c]; + slot->metrics.width += xstr; + slot->metrics.height += ystr; + slot->metrics.horiBearingY += ystr; + slot->metrics.horiAdvance += xstr; - - v_first = points[first]; - v_prev = points[last]; - v_cur = v_first; - - for ( n = first; n <= last; n++ ) - { - FT_Pos d; - FT_Vector in, out; - FT_Fixed scale; - FT_Angle angle_diff; - - - if ( n < last ) v_next = points[n + 1]; - else v_next = v_first; - - /* compute the in and out vectors */ - in.x = v_cur.x - v_prev.x; - in.y = v_cur.y - v_prev.y; - - out.x = v_next.x - v_cur.x; - out.y = v_next.y - v_cur.y; - - angle_in = FT_Atan2( in.x, in.y ); - angle_out = FT_Atan2( out.x, out.y ); - angle_diff = FT_Angle_Diff( angle_in, angle_out ); - scale = FT_Cos( angle_diff/2 ); - - if ( scale < 0x400L && scale > -0x400L ) - { - if ( scale >= 0 ) - scale = 0x400L; - else - scale = -0x400L; - } - - d = FT_DivFix( distance, scale ); - - FT_Vector_From_Polar( &in, d, angle_in + angle_diff/2 - rotate ); - - outline->points[n].x = v_cur.x + distance + in.x; - outline->points[n].y = v_cur.y + distance + in.y; - - v_prev = v_cur; - v_cur = v_next; - } - - first = last + 1; + slot->advance.x += xstr; } - - slot->metrics.horiAdvance = - ( slot->metrics.horiAdvance + distance*4 ) & ~63; } === src/base/rules.mk ================================================================== --- src/base/rules.mk (/freetype2/trunk) (revision 240) +++ src/base/rules.mk (/freetype2/branches/embolden) (local) @@ -60,6 +60,7 @@ $(BASE_DIR)/ftstroke.c \ $(BASE_DIR)/fttype1.c \ $(BASE_DIR)/ftwinfnt.c \ + $(BASE_DIR)/ftsynth.c \ $(BASE_DIR)/ftxf86.c # Default extensions objects