1 /***************************************************************************/
5 /* FreeType synthesizing code for emboldening and slanting (body). */
7 /* Copyright 2000-2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
20 #include FT_INTERNAL_OBJECTS_H
21 #include FT_INTERNAL_CALC_H
23 #include FT_SYNTHESIS_H
26 #define FT_BOLD_THRESHOLD 0x0100
29 /*************************************************************************/
30 /*************************************************************************/
32 /**** EXPERIMENTAL OBLIQUING SUPPORT ****/
34 /*************************************************************************/
35 /*************************************************************************/
37 FT_EXPORT_DEF( FT_Error )
38 FT_Outline_Oblique( FT_GlyphSlot original,
44 FT_UNUSED( original );
45 /* we don't touch the advance width */
50 /* For italic, simply apply a shear transform, with an angle */
51 /* of about 12 degrees. */
53 transform.xx = 0x10000L;
54 transform.yx = 0x00000L;
56 transform.xy = 0x06000L;
57 transform.yy = 0x10000L;
59 FT_Outline_Transform( outline, &transform );
65 /*************************************************************************/
66 /*************************************************************************/
68 /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/
70 /*************************************************************************/
71 /*************************************************************************/
74 /* Compute the norm of a vector */
76 #ifdef FT_CONFIG_OPTION_OLD_CALCS
79 ft_norm( FT_Vector* vec )
84 MUL_64( vec->x, vec->x, t1 );
85 MUL_64( vec->y, vec->y, t2 );
88 return (FT_Pos)SQRT_64( t1 );
91 #else /* FT_CONFIG_OPTION_OLD_CALCS */
94 ft_norm( FT_Vector* vec )
98 FT_ULong H, L, L2, hi, lo, med;
101 u = vec->x; if ( u < 0 ) u = -u;
102 v = vec->y; if ( v < 0 ) v = -v;
111 /* check that we are not trying to normalize zero! */
115 /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
116 hi = (FT_ULong)u >> 16;
117 lo = (FT_ULong)u & 0xFFFF;
120 H = hi * hi + ( med >> 15 );
126 hi = (FT_ULong)v >> 16;
127 lo = (FT_ULong)v & 0xFFFF;
130 H += hi * hi + ( med >> 15 );
140 /* if the value is smaller than 32 bits */
144 while ( ( L & 0xC0000000UL ) == 0 )
149 return ( FT_Sqrt32( L ) >> shift );
155 L = ( L >> 2 ) | ( H << 30 );
159 return ( FT_Sqrt32( L ) << shift );
163 #endif /* FT_CONFIG_OPTION_OLD_CALCS */
167 ft_test_extrema( FT_Outline* outline,
170 FT_Vector *prev, *cur, *next;
172 FT_Int c, first, last;
175 /* we need to compute the `previous' and `next' point */
176 /* for these extrema. */
177 cur = outline->points + n;
182 for ( c = 0; c < outline->n_contours; c++ )
184 last = outline->contours[c];
187 prev = outline->points + last;
190 next = outline->points + first;
195 product = FT_MulDiv( cur->x - prev->x, /* in.x */
196 next->y - cur->y, /* out.y */
199 FT_MulDiv( cur->y - prev->y, /* in.y */
200 next->x - cur->x, /* out.x */
204 product = product > 0 ? 1 : -1;
210 /* Compute the orientation of path filling. It differs between TrueType */
211 /* and Type1 formats. We could use the `ft_outline_reverse_fill' flag, */
212 /* but it is better to re-compute it directly (it seems that this flag */
213 /* isn't correctly set for some weird composite glyphs currently). */
215 /* We do this by computing bounding box points, and computing their */
218 /* The function returns either 1 or -1. */
221 ft_get_orientation( FT_Outline* outline )
233 box.xMin = box.yMin = 32767;
234 box.xMax = box.yMax = -32768;
237 if ( outline->n_contours < 1 )
240 last = outline->contours[outline->n_contours - 1];
242 for ( n = 0; n <= last; n++ )
247 x = outline->points[n].x;
259 y = outline->points[n].y;
272 /* test orientation of the xmin */
273 n = ft_test_extrema( outline, indices.xMin );
277 n = ft_test_extrema( outline, indices.yMin );
281 n = ft_test_extrema( outline, indices.xMax );
285 n = ft_test_extrema( outline, indices.yMax );
294 FT_EXPORT_DEF( FT_Error )
295 FT_Outline_Embolden( FT_GlyphSlot original,
301 FT_Vector cur, prev, next;
303 FT_Face face = FT_SLOT_FACE( original );
304 int c, n, first, orientation;
306 FT_UNUSED( advance );
309 /* compute control distance */
310 distance = FT_MulFix( face->units_per_EM / 60,
311 face->size->metrics.y_scale );
313 orientation = ft_get_orientation( &original->outline );
315 points = original->outline.points;
318 for ( c = 0; c < outline->n_contours; c++ )
320 int last = outline->contours[c];
325 for ( n = first; n <= last; n++ )
327 FT_Pos norm, delta, d;
332 if ( n < last ) next = points[n + 1];
333 else next = points[first];
335 /* compute the in and out vectors */
336 in.x = cur.x - prev.x;
337 in.y = cur.y - prev.y;
339 out.x = next.x - cur.x;
340 out.y = next.y - cur.y;
342 /* compute U and V */
343 norm = ft_norm( &in );
344 u.x = orientation * FT_DivFix( in.y, norm );
345 u.y = orientation * -FT_DivFix( in.x, norm );
347 norm = ft_norm( &out );
348 v.x = orientation * FT_DivFix( out.y, norm );
349 v.y = orientation * -FT_DivFix( out.x, norm );
353 if ( ( outline->tags[n] & FT_Curve_Tag_On ) == 0 )
356 /* Check discriminant for parallel vectors */
357 delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
358 if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
360 /* Move point -- compute A and B */
364 A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
365 B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
367 x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
368 y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
370 outline->points[n].x = distance + FT_DivFix( x, delta );
371 outline->points[n].y = distance + FT_DivFix( y, delta );
375 /* Vectors are nearly parallel */
379 x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
380 y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
382 outline->points[n].x = x;
383 outline->points[n].y = y;
393 *advance = ( *advance + distance * 4 ) & -64;