diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c index c7ffe8c41..248c38645 100644 --- a/src/base/ftglyph.c +++ b/src/base/ftglyph.c @@ -498,3 +498,305 @@ ; } } + + + /***************************************************************************/ + /***************************************************************************/ + /**** ****/ + /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/ + /**** ****/ + /***************************************************************************/ + /***************************************************************************/ + +#if 0 + +/* Compute the norm of a vector */ +#ifdef FT_CONFIG_OPTION_OLD_CALCS + static + FT_Pos ft_norm( FT_Vector* vec ) + { + FT_Int64 t1, t2; + + MUL_64( vec->x, vec->x, t1 ); + MUL_64( vec->y, vec->y, t2 ); + ADD_64( t1, t2, t1 ); + return (FT_Pos)SQRT_64(t1); + } +#else + static + FT_Pos ft_norm( FT_Vector* vec ) + { + FT_F26Dot6 u, v, d; + FT_Int shift; + FT_ULong H, L, L2, hi, lo, med; + + u = vec->x; if (u < 0) u = -u; + v = vec->y; if (v < 0) v = -v; + + if (u < v) + { + d = u; + u = v; + v = d; + } + + /* check that we're not trying to normalise zero !! */ + if (u==0) return 0; + + /* compute (u*u+v*v) on 64 bits with two 32-bit registers [H:L] */ + hi = (FT_ULong)u >> 16; + lo = (FT_ULong)u & 0xFFFF; + med = hi*lo; + + H = hi*hi + (med >> 15); + med <<= 17; + L = lo*lo + med; + if (L < med) H++; + + hi = (FT_ULong)v >> 16; + lo = (FT_ULong)v & 0xFFFF; + med = hi*lo; + + H += hi*hi + (med >> 15); + med <<= 17; + L2 = lo*lo + med; + if (L2 < med) H++; + + L += L2; + if (L < L2) H++; + + /* if the value is smaller than 32-bits */ + shift = 0; + if (H == 0) + { + while ((L & 0xC0000000) == 0) + { + L <<= 2; + shift++; + } + return (FT_Sqrt32(L) >> shift); + } + else + { + while (H) + { + L = (L >> 2) | (H << 30); + H >>= 2; + shift++; + } + return (FT_Sqrt32(L) << shift); + } + } +#endif + + static + int ft_test_extrema( FT_Outline* outline, + int n ) + { + FT_Vector *prev, *cur, *next; + FT_Pos product; + FT_Int first, last; + + /* we need to compute the "previous" and "next" point */ + /* for this extrema.. */ + cur = outline->points + n; + prev = cur - 1; + next = cur + 1; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + last = outline->contours[c]; + + if ( n == first ) + prev = outline->points + last; + + if ( n == last ) + next = outline->points + first; + + first = last + 1; + } + + product = FT_MulDiv( cur->x - prev->x, /* in.x */ + next->y - cur->y, /* out.y */ + 0x40 ) - + + FT_MulDiv( cur->y - prev->y, /* in.y */ + next->x - cur->x, /* out.x */ + 0x40 ); + + if (product) + product = ( product > 0 ? 1 : -1 ); + + return product; + } + + +/* Compute the orientation of path filling. It differs between TrueType */ +/* and Type1 formats. We could use the 'ft_outline_reverse_fill' flag, */ +/* but it's better to re-compute it directly (it seems that this flag */ +/* isn't correctly set for some weird composite glyphs for now).. */ +/* */ +/* We do this by computing bounding box points, and computing their */ +/* curvature.. the function returns either 1 or -1 */ +/* */ + static + int ft_get_orientation( FT_Outline* outline ) + { + FT_BBox box; + FT_BBox indexes; + int n, last; + + indexes.xMin = -1; + indexes.yMin = -1; + indexes.xMax = -1; + indexes.yMax = -1; + + box.xMin = box.yMin = 32767; + box.xMax = box.yMax = -32768; + + /* is it empty ? */ + if ( outline->n_contours < 1 ) + return 1; + + last = outline->contours[outline->n_contours-1]; + + for ( n = 0; n <= last; n++ ) + { + FT_Pos x, y; + + x = outline->points[n].x; + if ( x < box.xMin ) + { + box.xMin = x; + indexes.xMin = n; + } + + if ( x > box.xMax ) + { + box.xMax = x; + indexes.xMax = n; + } + + y = outline->points[n].y; + if ( y < box.yMin ) + { + box.yMin = y; + indexes.yMin = n; + } + + if ( y > box.yMax ) + { + box.yMax = y; + indexes.yMax = n; + } + } + + /* test orientation of the xmin */ + return ft_test_extrema( outline, indexes.xMin ) || + ft_test_extrema( outline, indexes.yMin ) || + ft_test_extrema( outline, indexes.xMax ) || + ft_test_extrema( outline, indexes.yMax ) || + 1; /* this is an empty glyph ?? */ + } + + + static + FT_Error ft_embolden( FT_Face original, + FT_Outline* outline, + FT_Pos* advance ) + { + FT_Vector u, v; + FT_Vector* points; + FT_Vector cur, prev, next; + FT_Pos distance; + int c, n, first, orientation; + + (void)advance; + + /* compute control distance */ + distance = FT_MulFix( original->em_size/60, + original->size->metrics.y_scale ); + + orientation = ft_get_orientation( &original->glyph->outline ); + + points = original->glyph->outline.points; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + int last = outline->contours[c]; + + prev = points[last]; + + for ( n = first; n <= last; n++ ) + { + FT_Pos norme, delta, d; + FT_Vector in, out; + + cur = points[n]; + if ( n < last ) next = points[n+1]; + else next = points[first]; + + /* compute the in and out vectors */ + in.x = cur.x - prev.x; + in.y = cur.y - prev.y; + + out.x = next.x - cur.x; + out.y = next.y - cur.y; + + /* compute U and V */ + norme = ft_norm( &in ); + u.x = orientation * FT_DivFix( in.y, norme ); + u.y = orientation * - FT_DivFix( in.x, norme ); + + norme = ft_norm( &out ); + v.x = orientation * FT_DivFix( out.y, norme ); + v.y = orientation * - FT_DivFix( out.x, norme ); + + d = distance; + + if ( (outline->flags[n] & FT_Curve_Tag_On) == 0 ) + d *= 2; + + /* Check discriminant for parallel vectors */ + delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x ); + if ( delta > FT_BOLD_THRESHOLD || delta < - FT_BOLD_THRESHOLD ) + { + /* Move point - compute A and B */ + FT_Pos x, y, A, B; + + A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y ); + B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y ); + + x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y ); + y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x ); + + outline->points[n].x = distance + FT_DivFix( x, delta ); + outline->points[n].y = distance + FT_DivFix( y, delta ); + } + else + { + /* Vectors are nearly parallel */ + FT_Pos x, y; + + x = distance + cur.x + FT_MulFix( d, u.x + v.x )/2; + y = distance + cur.y + FT_MulFix( d, u.y + v.y )/2; + + outline->points[n].x = x; + outline->points[n].y = y; + } + + prev = cur; + } + + first = last+1; + } + + if (advance) + *advance = (*advance + distance*4) & -64; + + return 0; + } + +#endif /* 0 - EXPERIMENTAL STUFF !! */