On Tue, May 24, 2005 at 04:05:39PM +0200, Werner LEMBERG wrote:
>
> > This patch implements FT_Bitmap_Embolden and FT_Outline_Embolden.
> > It is intended for testing the algorithm and for discussing what
> > arguments should these function calls take.
>
> Since David has fixed the problem (and rejected your modifications
> because of too great distortions under some circumstances), can you
> update your patch?
>
Updated.
You may think of this patch as:
1. moving outline emboldening code from FT_GlyphSlot_Embolden to
FT_Outline_Embolden,
2. implementing FT_Bitmap_Embolden, and
3. making FT_GlyphSlot_Embolden depend on both of them.
And as the previous one, both FT_Outline_Embolden and FT_Bitmap_Embolden
needs discussions on what arguments they should take.
> > I also make FT_GlyphSlot_Embolden to use these function calls. You
> > can see it as an example of how applications are gonna use the
> > function calls and it will eventually be removed.
>
> You mean FT_GlyphSlot_Embolden shall not be added to the library?
A glyph slot should be for glyph loading, not for glyph manipulations.
So I think a FT_Glyph_Embolden might be better.
> Then I suggest that you add this functionality to ftview instead.
=== include/freetype/ftbitmap.h
==================================================================
--- include/freetype/ftbitmap.h (/freetype2/trunk) (revision 898)
+++ include/freetype/ftbitmap.h (/freetype2/branches/embolden) (local)
@@ -92,6 +92,42 @@
/*************************************************************************/
/* */
/* <Function> */
+ /* FT_Bitmap_Embolden */
+ /* */
+ /* <Description> */
+ /* Emboldens a bitmap. The new bitmap will be about xStrength */
+ /* pixels wider and yStrength pixels higher. (The left and bottom */
+ /* borders are kept unchanged) */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* <InOut> */
+ /* 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. */
+ /* */
+ /* <Return> */
+ /* FreeType error code */
+ /* */
+ /* <Note> */
+ /* 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 );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* FT_Bitmap_Convert */
/* */
/* <Description> */
=== include/freetype/ftoutln.h
==================================================================
--- include/freetype/ftoutln.h (/freetype2/trunk) (revision 898)
+++ 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,30 @@
/*************************************************************************/
/* */
/* <Function> */
+ /* FT_Outline_Embolden */
+ /* */
+ /* <Description> */
+ /* 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. */
+ /* */
+ /* <InOut> */
+ /* outline :: A handle to the target outline. */
+ /* */
+ /* <Input> */
+ /* strength :: How strong the glyph is emboldened. Expressed in 16.16 */
+ /* pixel format. */
+ /* */
+ /* <Return> */
+ /* FreeType error code */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Embolden( FT_Outline* outline,
+ FT_Pos strength );
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* FT_Outline_Reverse */
/* */
/* <Description> */
=== src/base/ftbitmap.c
==================================================================
--- src/base/ftbitmap.c (/freetype2/trunk) (revision 898)
+++ 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 898)
+++ src/base/ftoutln.c (/freetype2/branches/embolden) (local)
@@ -670,6 +670,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 )
FT_Outline_Get_Orientation( FT_Outline* outline )
{
=== src/base/ftsynth.c
==================================================================
--- src/base/ftsynth.c (/freetype2/trunk) (revision 898)
+++ src/base/ftsynth.c (/freetype2/branches/embolden) (local)
@@ -17,11 +17,10 @@
#include <ft2build.h>
+#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,86 +76,51 @@
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 );
+ 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 );
- 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];
+#if 0
+ slot->advance.x += 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 < 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;
+ slot->metrics.width += xstr;
+ slot->metrics.height += ystr;
+ slot->metrics.horiBearingY += ystr;
+#endif
+ slot->metrics.horiAdvance += xstr;
}
-
- slot->metrics.horiAdvance =
- ( slot->metrics.horiAdvance + distance*4 ) & ~63;
}
Property changes on:
___________________________________________________________________
Name: svk:merge
+5f392c16-9bf0-0310-b16c-a65848a4e34f:/freetype2/trunk:895
_______________________________________________
Freetype mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/freetype