ref: 890f807a7b053179b42860a32fe9a0ed835be2be
parent: 0d9be1c31e0e056881f4bb0b61f82e6ffdd06b9e
author: Wu, Chia-I (吳佳一) <[email protected]>
date: Wed Feb 22 15:47:39 EST 2006
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-02-23 Chia-I Wu <[email protected]>
+
+ * 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 <[email protected]>
* modules.cfg: Compile in ftotval.c and ftxf86.c by default for ABI
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -465,6 +465,11 @@
* 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
{
@@ -471,7 +476,8 @@
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;
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -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;
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -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;
}