diff --git a/ChangeLog b/ChangeLog index f57fb4f78..bbd4b78cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2005-05-24 Werner Lemberg + + * docs/CHANGES: Updated. + +2005-05-24 Chia I Wu + + * include/freetype/ftbitmap.h (FT_Bitmap_Embolden): New declaration. + + * include/freetype/ftoutln.h (FT_Outline_Embolden): New declaration. + + * src/base/ftbitmap.c (ft_bitmap_assure_buffer): New auxiliary + function. + (FT_Bitmap_Embolden): New function. + + * src/base/ftoutln.c (FT_Outline_Embolden): New function. + + * src/base/ftsynth.c: Don't include FT_INTERNAL_CALC_H and + FT_TRIGONOMETRY_H but FT_BITMAP_H. + (FT_GlyphSlot_Embolden): Use FT_Outline_Embolden or + FT_Bitmap_Embolden. + 2005-05-24 Werner Lemberg * configure: Always remove config.mk, builds/unix/unix-def.mk, and diff --git a/docs/CHANGES b/docs/CHANGES index 0b5c29996..6cbec640f 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -60,10 +60,17 @@ LATEST CHANGES BETWEEN 2.1.10 and 2.1.9 for errors in those tables while accessing them. - A new API in FT_BITMAP_H (`FT_Bitmap_New', `FT_Bitmap_Convert', - `FT_Bitmap_Copy', `FT_Bitmap_Done') has been added. Its use is - to convert an FT_Bitmap structure in 1bpp, 2bpp, 4bpp, or 8bpp - format into another 8bpp FT_Bitmap, probably using a different - pitch. + `FT_Bitmap_Copy', `FT_Bitmap_Embolden', `FT_Bitmap_Done') has + been added. Its use is to convert an FT_Bitmap structure in + 1bpp, 2bpp, 4bpp, or 8bpp format into another 8bpp FT_Bitmap, + probably using a different pitch, and to further manipulate it. + + - A new API `FT_Outline_Embolden' (in FT_OUTLINE_H) gives finer + control how outlines are embolded. + + - `FT_GlyphSlot_Embolden' (in FT_SYNTHESIS_H) now handles bitmaps + also (code contributed by Chia I Wu). Note that this function + is still experimental and may be replaced with a better API. - The method how BDF and PCF bitmap fonts are accessed has been refined. Formerly, FT_Set_Pixel_Sizes and FT_Set_Char_Size diff --git a/include/freetype/ftbitmap.h b/include/freetype/ftbitmap.h index 68218df6b..8aae8c686 100644 --- a/include/freetype/ftbitmap.h +++ b/include/freetype/ftbitmap.h @@ -89,6 +89,42 @@ FT_BEGIN_HEADER FT_Bitmap *target); + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* 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. */ + /* */ + /* */ + /* bitmap :: A handle to the target bitmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The 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 ); + + /*************************************************************************/ /* */ /* */ diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h index a6c602ab9..543f1512e 100644 --- a/include/freetype/ftoutln.h +++ b/include/freetype/ftoutln.h @@ -58,6 +58,7 @@ FT_BEGIN_HEADER /* FT_Outline_Copy */ /* FT_Outline_Translate */ /* FT_Outline_Transform */ + /* FT_Outline_Embolden */ /* FT_Outline_Reverse */ /* FT_Outline_Check */ /* */ @@ -303,6 +304,31 @@ FT_BEGIN_HEADER const FT_Matrix* matrix ); + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Embolden */ + /* */ + /* */ + /* Emboldens an outline. The new outline will be at most 4 times */ + /* `strength' pixels wider and higher. You may think of the left and */ + /* bottom borders as unchanged. */ + /* */ + /* */ + /* outline :: A handle to the target outline. */ + /* */ + /* */ + /* strength :: How strong the glyph is emboldened. Expressed in */ + /* 16.16 pixel format. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Embolden( FT_Outline* outline, + FT_Pos strength ); + + /*************************************************************************/ /* */ /* */ diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c index 6d208e64c..9de9e8f57 100644 --- a/src/base/ftbitmap.c +++ b/src/base/ftbitmap.c @@ -94,6 +94,188 @@ } + 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; + FT_UInt ppb; + FT_Int 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; + } + + /* check whether we must allocate memory */ + 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; + FT_Int i, x, y, pitch; + FT_Int xstr, ystr; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !bitmap ) + 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; + } + + xstr = FT_PIX_ROUND( xStrength ) >> 6; + ystr = FT_PIX_ROUND( 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 maximum value of 8 for `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 ) diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 8eed85ce8..d2e53cd77 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -668,6 +668,89 @@ } + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Embolden( FT_Outline* outline, + FT_Pos strength ) + { + 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 ) + return FT_Err_Invalid_Argument; + + if ( strength == 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; + FT_Pos d; + FT_Fixed scale; + + + 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 < 0x4000L && scale > -0x4000L ) + in.x = in.y = 0; + else + { + d = FT_DivFix( strength, 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; + + v_prev = v_cur; + v_cur = v_next; + } + + first = last + 1; + } + + return FT_Err_Ok; + } + + /* documentation is in ftoutln.h */ FT_EXPORT_DEF( FT_Orientation ) diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c index 5969af99b..2529354c8 100644 --- a/src/base/ftsynth.c +++ b/src/base/ftsynth.c @@ -4,7 +4,7 @@ /* */ /* FreeType synthesizing code for emboldening and slanting (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,11 +17,10 @@ #include -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_CALC_H -#include FT_OUTLINE_H -#include FT_TRIGONOMETRY_H #include FT_SYNTHESIS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_OUTLINE_H +#include FT_BITMAP_H #define FT_BOLD_THRESHOLD 0x0100 @@ -77,86 +76,50 @@ 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 ( 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++ ) + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) { - int last = outline->contours[c]; - - - 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 < 0x4000L && scale > -0x4000L ) - { - in.x = in.y = 0; - } - else - { - 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; + error = FT_Outline_Embolden( &slot->outline, xstr ); + xstr = ( xstr * 4 ) & ~63; + ystr = xstr; } + else if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) + { + xstr = FT_PIX_FLOOR( xstr ); + if ( xstr == 0 ) + xstr = 1 << 6; + ystr = FT_PIX_FLOOR( ystr ); - slot->metrics.horiAdvance = - ( slot->metrics.horiAdvance + distance*4 ) & ~63; + error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr ); + + /* XXX should we set these? */ + if ( !error ) + slot->bitmap_top += ystr >> 6; + } + else + error = FT_Err_Invalid_Argument; + + /* XXX should we set these? */ + if ( !error ) + { +#if 0 + slot->advance.x += xstr; + slot->metrics.width += xstr; + slot->metrics.height += ystr; + slot->metrics.horiBearingY += ystr; +#endif + slot->metrics.horiAdvance += xstr; + } }