* include/freetype/ftoutln.h (enum FT_Orientation): New value

`FT_ORIENTATION_NONE'.

* src/base/ftoutln.c (FT_OUTLINE_GET_CONTOUR, ft_contour_has,
ft_contour_enclosed, ft_outline_get_orientation): Another version of
`FT_Outline_Get_Orientation'.  This version differs from the public
one in that each part (contour not enclosed in another contour) of the
outline is checked for orientation.
(FT_Outline_Embolden): Use `ft_outline_get_orientation'.

* src/base/ftsynth.c (FT_GlyphSlot_Embolden): Render the outline and
use bitmap's embolden routine when the outline one failed.
This commit is contained in:
Wu, Chia-I (吳佳一) 2006-02-22 20:47:39 +00:00
parent 0d9be1c31e
commit 890f807a7b
4 changed files with 233 additions and 33 deletions

View File

@ -1,3 +1,18 @@
2006-02-23 Chia-I Wu <b90201047@ntu.edu.tw>
* include/freetype/ftoutln.h (enum FT_Orientation): New value
`FT_ORIENTATION_NONE'.
* src/base/ftoutln.c (FT_OUTLINE_GET_CONTOUR, ft_contour_has,
ft_contour_enclosed, ft_outline_get_orientation): Another version of
`FT_Outline_Get_Orientation'. This version differs from the public
one in that each part (contour not enclosed in another contour) of the
outline is checked for orientation.
(FT_Outline_Embolden): Use `ft_outline_get_orientation'.
* src/base/ftsynth.c (FT_GlyphSlot_Embolden): Render the outline and
use bitmap's embolden routine when the outline one failed.
2006-02-22 Chia-I Wu <b90201047@ntu.edu.tw>
* modules.cfg: Compile in ftotval.c and ftxf86.c by default for ABI

View File

@ -465,13 +465,19 @@ FT_BEGIN_HEADER
* This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
* remember that in Postscript, everything that is to the left of
* the drawing direction of a contour must be filled.
*
* FT_ORIENTATION_NONE ::
* The orientation cannot be determined. That is, different part of the
* glyph has different orientation.
*
*/
typedef enum
{
FT_ORIENTATION_TRUETYPE = 0,
FT_ORIENTATION_POSTSCRIPT = 1,
FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE,
FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT
FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT,
FT_ORIENTATION_NONE
} FT_Orientation;

View File

@ -668,6 +668,168 @@
}
#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \
do { \
( first ) = ( c > 0 ) ? ( outline )->points + \
( outline )->contours[c - 1] + 1 \
: ( outline )->points; \
( last ) = ( outline )->points + ( outline )->contours[c]; \
} while ( 0 )
/* Is a point in some contour? */
/* */
/* We treat every point of the contour as if it */
/* it is ON. That is, we allow false positive, */
/* but disallow false negative. (XXX really?) */
static FT_Bool
ft_contour_has( FT_Outline* outline,
FT_Short c,
FT_Vector* point )
{
FT_Vector* first;
FT_Vector* last;
FT_Vector* a;
FT_Vector* b;
FT_UInt n = 0;
FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
for ( a = first; a <= last; a++ )
{
FT_Pos x;
FT_Int intersect;
b = ( a == last ) ? first : a + 1;
intersect = ( a->y - point->y ) ^ ( b->y - point->y );
/* a and b are on the same side */
if ( intersect >= 0 )
{
if ( intersect == 0 && a->y == point->y )
{
if ( ( a->x <= point->x && b->x >= point->x ) ||
( a->x >= point->x && b->x <= point->x ) )
return 1;
}
continue;
}
x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
if ( x < point->x )
n++;
else if ( x == point->x )
return 1;
}
return ( n % 2 );
}
static FT_Bool
ft_contour_enclosed( FT_Outline* outline,
FT_UShort c )
{
FT_Vector* first;
FT_Vector* last;
FT_Short i;
FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
for ( i = 0; i < outline->n_contours; i++ )
{
if ( i != c && ft_contour_has( outline, i, first ) )
{
FT_Vector* pt;
for ( pt = first + 1; pt <= last; pt++ )
if ( !ft_contour_has( outline, i, pt ) )
return 0;
return 1;
}
}
return 0;
}
/* This version differs from the public one in that each */
/* part (contour not enclosed in another contour) of the */
/* outline is checked for orientation. This is */
/* necessary for some buggy CJK fonts. */
static FT_Orientation
ft_outline_get_orientation( FT_Outline* outline )
{
FT_Short i;
FT_Vector* first;
FT_Vector* last;
FT_Orientation orient = FT_ORIENTATION_NONE;
first = outline->points;
for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
{
FT_Vector* point;
FT_Vector* xmin_point;
FT_Pos xmin;
last = outline->points + outline->contours[i];
/* skip degenerate contours */
if ( last < first + 2 )
continue;
if ( ft_contour_enclosed( outline, i ) )
continue;
xmin = first->x;
xmin_point = first;
for ( point = first + 1; point <= last; point++ )
{
if ( point->x < xmin )
{
xmin = point->x;
xmin_point = point;
}
}
/* check the orientation of the contour */
{
FT_Vector* prev;
FT_Vector* next;
FT_Orientation o;
prev = ( xmin_point == first ) ? last : xmin_point - 1;
next = ( xmin_point == last ) ? first : xmin_point + 1;
if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
o = FT_ORIENTATION_POSTSCRIPT;
else
o = FT_ORIENTATION_TRUETYPE;
if ( orient == FT_ORIENTATION_NONE )
orient = o;
else if ( orient != o )
return FT_ORIENTATION_NONE;
}
}
return orient;
}
/* documentation is in ftoutln.h */
FT_EXPORT_DEF( FT_Error )
@ -678,6 +840,7 @@
FT_Vector v_prev, v_first, v_next, v_cur;
FT_Angle rotate, angle_in, angle_out;
FT_Int c, n, first;
FT_Int orientation;
if ( !outline )
@ -687,7 +850,16 @@
if ( strength == 0 )
return FT_Err_Ok;
if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_TRUETYPE )
orientation = ft_outline_get_orientation( outline );
if ( orientation == FT_ORIENTATION_NONE )
{
if ( outline->n_contours )
return FT_Err_Invalid_Argument;
else
return FT_Err_Ok;
}
if ( orientation == FT_ORIENTATION_TRUETYPE )
rotate = -FT_ANGLE_PI2;
else
rotate = FT_ANGLE_PI2;

View File

@ -75,10 +75,14 @@
{
FT_Library library = slot->library;
FT_Face face = FT_SLOT_FACE( slot );
FT_Error error = FT_Err_Ok;
FT_Error error;
FT_Pos xstr, ystr;
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
slot->format != FT_GLYPH_FORMAT_BITMAP )
return;
/* some reasonable strength */
xstr = FT_MulFix( face->units_per_EM,
face->size->metrics.y_scale ) / 24;
@ -87,13 +91,22 @@
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
{
error = FT_Outline_Embolden( &slot->outline, xstr );
/* this is more than enough for most glyphs; */
/* if you need accurate values, you have to call FT_Outline_Get_CBox */
xstr = xstr * 2;
ystr = xstr;
if ( error )
{
error = FT_Render_Glyph( slot, FT_RENDER_MODE_NORMAL );
if ( error )
return;
}
else
{
/* this is more than enough for most glyphs; */
/* if you need accurate values, you have to call FT_Outline_Get_CBox */
xstr = xstr * 2;
ystr = xstr;
}
}
else if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
{
xstr = FT_PIX_FLOOR( xstr );
if ( xstr == 0 )
@ -108,37 +121,31 @@
FT_Bitmap_New( &bitmap );
error = FT_Bitmap_Copy( library, &slot->bitmap, &bitmap );
if ( error )
return;
if ( !error )
{
slot->bitmap = bitmap;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
}
slot->bitmap = bitmap;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
}
if ( !error )
error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
if ( error )
return;
}
else
error = FT_Err_Invalid_Argument;
/* modify the metrics accordingly */
if ( !error )
{
/* assume the layout is horizontal */
slot->advance.x += xstr;
/* assume the layout is horizontal */
slot->advance.x += xstr;
slot->metrics.width += xstr;
slot->metrics.height += ystr;
slot->metrics.horiBearingY += ystr;
slot->metrics.horiAdvance += xstr;
slot->metrics.vertBearingX -= xstr / 2;
slot->metrics.vertBearingY += ystr;
slot->metrics.vertAdvance += ystr;
slot->metrics.width += xstr;
slot->metrics.height += ystr;
slot->metrics.horiBearingY += ystr;
slot->metrics.horiAdvance += xstr;
slot->metrics.vertBearingX -= xstr / 2;
slot->metrics.vertBearingY += ystr;
slot->metrics.vertAdvance += ystr;
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
slot->bitmap_top += ystr >> 6;
}
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
slot->bitmap_top += ystr >> 6;
}