From 727dee178a392d20eb050d0c446f2fcc29058fa1 Mon Sep 17 00:00:00 2001 From: Victoria Lease Date: Mon, 10 Jun 2013 13:55:54 -0700 Subject: Update freetype to 5e094c6fb2ddd6e8901a5679e2cbb8fa476a38ee Integrated patches from freetype2 git repository, up to hashval 5e094c6fb2ddd6e8901a5679e2cbb8fa476a38ee, which is post-2.4.12. Most recent commit message from freetype git: [truetype] Improve handling of broken sbit advance widths. Noteworthy patches included: [cff] Add a new Type 2 interpreter and hinter. Add support for color embedded bitmaps (eg. color emoji). Change-Id: Ia8b6a67bc18f841b24f44edf80f81f663185b598 --- src/base/ftoutln.c | 298 ++++++++++++++++++++++------------------------------- 1 file changed, 125 insertions(+), 173 deletions(-) (limited to 'src/base/ftoutln.c') diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 9ae276d..54ca5cd 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -4,7 +4,7 @@ /* */ /* FreeType outline management (body). */ /* */ -/* Copyright 1996-2008, 2010, 2012 by */ +/* Copyright 1996-2008, 2010, 2012-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -26,6 +26,7 @@ #include #include FT_OUTLINE_H #include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_CALC_H #include FT_INTERNAL_DEBUG_H #include FT_TRIGONOMETRY_H @@ -73,7 +74,7 @@ if ( !outline || !func_interface ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); shift = func_interface->shift; delta = func_interface->delta; @@ -286,7 +287,7 @@ return error; Invalid_Outline: - return FT_Err_Invalid_Outline; + return FT_THROW( Invalid_Outline ); } @@ -300,10 +301,17 @@ if ( !anoutline || !memory ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); *anoutline = null_outline; + if ( numContours < 0 || + (FT_UInt)numContours > numPoints ) + return FT_THROW( Invalid_Argument ); + + if ( numPoints > FT_OUTLINE_POINTS_MAX ) + return FT_THROW( Array_Too_Large ); + if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || FT_NEW_ARRAY( anoutline->tags, numPoints ) || FT_NEW_ARRAY( anoutline->contours, numContours ) ) @@ -332,7 +340,7 @@ FT_Outline *anoutline ) { if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); return FT_Outline_New_Internal( library->memory, numPoints, numContours, anoutline ); @@ -380,7 +388,7 @@ } Bad: - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); } @@ -396,7 +404,7 @@ if ( !source || !target || source->n_points != target->n_points || source->n_contours != target->n_contours ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); if ( source == target ) return FT_Err_Ok; @@ -435,7 +443,7 @@ return FT_Err_Ok; } else - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); } @@ -448,7 +456,7 @@ /* check for valid `outline' in FT_Outline_Done_Internal() */ if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); return FT_Outline_Done_Internal( library->memory, outline ); } @@ -602,21 +610,21 @@ if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); if ( !outline || !params ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); renderer = library->cur_renderer; node = library->renderers.head; params->source = (void*)outline; - error = FT_Err_Cannot_Render_Glyph; + error = FT_ERR( Cannot_Render_Glyph ); while ( renderer ) { error = renderer->raster_render( renderer->raster, params ); - if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) + if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) break; /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ @@ -650,7 +658,7 @@ if ( !abitmap ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); /* other checks are delayed to FT_Outline_Render() */ @@ -881,86 +889,127 @@ FT_EXPORT_DEF( FT_Error ) FT_Outline_Embolden( FT_Outline* outline, FT_Pos strength ) + { + return FT_Outline_EmboldenXY( outline, strength, strength ); + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_EmboldenXY( 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; FT_Int orientation; if ( !outline ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); - strength /= 2; - if ( strength == 0 ) + xstrength /= 2; + ystrength /= 2; + if ( xstrength == 0 && ystrength == 0 ) return FT_Err_Ok; orientation = FT_Outline_Get_Orientation( outline ); if ( orientation == FT_ORIENTATION_NONE ) { if ( outline->n_contours ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); else return FT_Err_Ok; } - if ( orientation == 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]; + FT_Vector in, out, shift; + FT_Fixed l_in, l_out, l, q, d; + int last = outline->contours[c]; v_first = points[first]; v_prev = points[last]; v_cur = v_first; - for ( n = first; n <= last; n++ ) + /* compute incoming normalized vector */ + in.x = v_cur.x - v_prev.x; + in.y = v_cur.y - v_prev.y; + l_in = FT_Vector_Length( &in ); + if ( l_in ) { - FT_Vector in, out; - FT_Angle angle_diff; - FT_Pos d; - FT_Fixed scale; - + in.x = FT_DivFix( in.x, l_in ); + in.y = FT_DivFix( in.y, l_in ); + } + for ( n = first; n <= last; n++ ) + { 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; - + /* compute outgoing normalized vector */ out.x = v_next.x - v_cur.x; out.y = v_next.y - v_cur.y; + l_out = FT_Vector_Length( &out ); + if ( l_out ) + { + out.x = FT_DivFix( out.x, l_out ); + out.y = FT_DivFix( out.y, l_out ); + } - 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 ); + d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); - if ( scale < 0x4000L && scale > -0x4000L ) - in.x = in.y = 0; - else + /* shift only if turn is less than ~160 degrees */ + if ( d > -0xF000L ) { - d = FT_DivFix( strength, scale ); + d = d + 0x10000L; - FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate ); + /* shift components are aligned along lateral bisector */ + /* and directed according to the outline orientation. */ + shift.x = in.y + out.y; + shift.y = in.x + out.x; + + if ( orientation == FT_ORIENTATION_TRUETYPE ) + shift.x = -shift.x; + else + shift.y = -shift.y; + + /* restrict shift magnitude to better handle collapsing segments */ + q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); + if ( orientation == FT_ORIENTATION_TRUETYPE ) + q = -q; + + l = FT_MIN( l_in, l_out ); + + /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ + if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) ) + shift.x = FT_MulDiv( shift.x, xstrength, d ); + else + shift.x = FT_MulDiv( shift.x, l, q ); + + + if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) ) + shift.y = FT_MulDiv( shift.y, ystrength, d ); + else + shift.y = FT_MulDiv( shift.y, l, q ); } + else + shift.x = shift.y = 0; - outline->points[n].x = v_cur.x + strength + in.x; - outline->points[n].y = v_cur.y + strength + in.y; + outline->points[n].x = v_cur.x + xstrength + shift.x; + outline->points[n].y = v_cur.y + ystrength + shift.y; - v_prev = v_cur; - v_cur = v_next; + in = out; + l_in = l_out; + v_cur = v_next; } first = last + 1; @@ -975,23 +1024,12 @@ FT_EXPORT_DEF( FT_Orientation ) FT_Outline_Get_Orientation( FT_Outline* outline ) { - FT_Pos xmin = 32768L; - FT_Pos xmin_ymin = 32768L; - FT_Pos xmin_ymax = -32768L; - FT_Vector* xmin_first = NULL; - FT_Vector* xmin_last = NULL; - - short* contour; - - FT_Vector* first; - FT_Vector* last; - FT_Vector* prev; - FT_Vector* point; - - int i; - FT_Pos ray_y[3]; - FT_Orientation result[3] = - { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE }; + FT_BBox cbox; + FT_Int xshift, yshift; + FT_Vector* points; + FT_Vector v_prev, v_cur; + FT_Int c, n, first; + FT_Pos area = 0; if ( !outline || outline->n_points <= 0 ) @@ -1002,127 +1040,41 @@ /* cubic or quadratic curves, this test deals with the polygon */ /* only which is spanned up by the control points. */ - first = outline->points; - for ( contour = outline->contours; - contour < outline->contours + outline->n_contours; - contour++, first = last + 1 ) - { - FT_Pos contour_xmin = 32768L; - FT_Pos contour_xmax = -32768L; - FT_Pos contour_ymin = 32768L; - FT_Pos contour_ymax = -32768L; - - - last = outline->points + *contour; + FT_Outline_Get_CBox( outline, &cbox ); - /* skip degenerate contours */ - if ( last < first + 2 ) - continue; - - for ( point = first; point <= last; ++point ) - { - if ( point->x < contour_xmin ) - contour_xmin = point->x; - - if ( point->x > contour_xmax ) - contour_xmax = point->x; - - if ( point->y < contour_ymin ) - contour_ymin = point->y; - - if ( point->y > contour_ymax ) - contour_ymax = point->y; - } - - if ( contour_xmin < xmin && - contour_xmin != contour_xmax && - contour_ymin != contour_ymax ) - { - xmin = contour_xmin; - xmin_ymin = contour_ymin; - xmin_ymax = contour_ymax; - xmin_first = first; - xmin_last = last; - } - } + xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14; + xshift = FT_MAX( xshift, 0 ); - if ( xmin == 32768L ) - return FT_ORIENTATION_TRUETYPE; + yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14; + yshift = FT_MAX( yshift, 0 ); - ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2; - ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1; - ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2; + points = outline->points; - for ( i = 0; i < 3; i++ ) + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) { - FT_Pos left_x; - FT_Pos right_x; - FT_Vector* left1; - FT_Vector* left2; - FT_Vector* right1; - FT_Vector* right2; - + FT_Int last = outline->contours[c]; - RedoRay: - left_x = 32768L; - right_x = -32768L; - left1 = left2 = right1 = right2 = NULL; + v_prev = points[last]; - prev = xmin_last; - for ( point = xmin_first; point <= xmin_last; prev = point, ++point ) + for ( n = first; n <= last; n++ ) { - FT_Pos tmp_x; - - - if ( point->y == ray_y[i] || prev->y == ray_y[i] ) - { - ray_y[i]++; - goto RedoRay; - } - - if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) || - ( point->y > ray_y[i] && prev->y > ray_y[i] ) ) - continue; - - tmp_x = FT_MulDiv( point->x - prev->x, - ray_y[i] - prev->y, - point->y - prev->y ) + prev->x; - - if ( tmp_x < left_x ) - { - left_x = tmp_x; - left1 = prev; - left2 = point; - } - - if ( tmp_x > right_x ) - { - right_x = tmp_x; - right1 = prev; - right2 = point; - } + v_cur = points[n]; + area += ( ( v_cur.y - v_prev.y ) >> yshift ) * + ( ( v_cur.x + v_prev.x ) >> xshift ); + v_prev = v_cur; } - if ( left1 && right1 ) - { - if ( left1->y < left2->y && right1->y > right2->y ) - result[i] = FT_ORIENTATION_TRUETYPE; - else if ( left1->y > left2->y && right1->y < right2->y ) - result[i] = FT_ORIENTATION_POSTSCRIPT; - else - result[i] = FT_ORIENTATION_NONE; - } + first = last + 1; } - if ( result[0] != FT_ORIENTATION_NONE && - ( result[0] == result[1] || result[0] == result[2] ) ) - return result[0]; - - if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] ) - return result[1]; - - return FT_ORIENTATION_TRUETYPE; + if ( area > 0 ) + return FT_ORIENTATION_POSTSCRIPT; + else if ( area < 0 ) + return FT_ORIENTATION_TRUETYPE; + else + return FT_ORIENTATION_NONE; } -- cgit v1.2.3