1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftsynth.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType synthesizing code for emboldening and slanting (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2000-2001 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H 22*37da2899SCharles.Forsyth #include FT_OUTLINE_H 23*37da2899SCharles.Forsyth #include FT_TRIGONOMETRY_H 24*37da2899SCharles.Forsyth #include FT_SYNTHESIS_H 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth #define FT_BOLD_THRESHOLD 0x0100 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth /*************************************************************************/ 31*37da2899SCharles.Forsyth /*************************************************************************/ 32*37da2899SCharles.Forsyth /**** ****/ 33*37da2899SCharles.Forsyth /**** EXPERIMENTAL OBLIQUING SUPPORT ****/ 34*37da2899SCharles.Forsyth /**** ****/ 35*37da2899SCharles.Forsyth /*************************************************************************/ 36*37da2899SCharles.Forsyth /*************************************************************************/ 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_GlyphSlot_Oblique(FT_GlyphSlot slot)39*37da2899SCharles.Forsyth FT_GlyphSlot_Oblique( FT_GlyphSlot slot ) 40*37da2899SCharles.Forsyth { 41*37da2899SCharles.Forsyth FT_Matrix transform; 42*37da2899SCharles.Forsyth FT_Outline* outline = &slot->outline; 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth /* only oblique outline glyphs */ 46*37da2899SCharles.Forsyth if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) 47*37da2899SCharles.Forsyth return; 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth /* we don't touch the advance width */ 50*37da2899SCharles.Forsyth 51*37da2899SCharles.Forsyth /* For italic, simply apply a shear transform, with an angle */ 52*37da2899SCharles.Forsyth /* of about 12 degrees. */ 53*37da2899SCharles.Forsyth 54*37da2899SCharles.Forsyth transform.xx = 0x10000L; 55*37da2899SCharles.Forsyth transform.yx = 0x00000L; 56*37da2899SCharles.Forsyth 57*37da2899SCharles.Forsyth transform.xy = 0x06000L; 58*37da2899SCharles.Forsyth transform.yy = 0x10000L; 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth FT_Outline_Transform( outline, &transform ); 61*37da2899SCharles.Forsyth } 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth /*************************************************************************/ 65*37da2899SCharles.Forsyth /*************************************************************************/ 66*37da2899SCharles.Forsyth /**** ****/ 67*37da2899SCharles.Forsyth /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/ 68*37da2899SCharles.Forsyth /**** ****/ 69*37da2899SCharles.Forsyth /*************************************************************************/ 70*37da2899SCharles.Forsyth /*************************************************************************/ 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth 73*37da2899SCharles.Forsyth 74*37da2899SCharles.Forsyth static int ft_test_extrema(FT_Outline * outline,int n)75*37da2899SCharles.Forsyth ft_test_extrema( FT_Outline* outline, 76*37da2899SCharles.Forsyth int n ) 77*37da2899SCharles.Forsyth { 78*37da2899SCharles.Forsyth FT_Vector *prev, *cur, *next; 79*37da2899SCharles.Forsyth FT_Pos product; 80*37da2899SCharles.Forsyth FT_Int c, first, last; 81*37da2899SCharles.Forsyth 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth /* we need to compute the `previous' and `next' point */ 84*37da2899SCharles.Forsyth /* for these extrema. */ 85*37da2899SCharles.Forsyth cur = outline->points + n; 86*37da2899SCharles.Forsyth prev = cur - 1; 87*37da2899SCharles.Forsyth next = cur + 1; 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth first = 0; 90*37da2899SCharles.Forsyth for ( c = 0; c < outline->n_contours; c++ ) 91*37da2899SCharles.Forsyth { 92*37da2899SCharles.Forsyth last = outline->contours[c]; 93*37da2899SCharles.Forsyth 94*37da2899SCharles.Forsyth if ( n == first ) 95*37da2899SCharles.Forsyth prev = outline->points + last; 96*37da2899SCharles.Forsyth 97*37da2899SCharles.Forsyth if ( n == last ) 98*37da2899SCharles.Forsyth next = outline->points + first; 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth first = last + 1; 101*37da2899SCharles.Forsyth } 102*37da2899SCharles.Forsyth 103*37da2899SCharles.Forsyth product = FT_MulDiv( cur->x - prev->x, /* in.x */ 104*37da2899SCharles.Forsyth next->y - cur->y, /* out.y */ 105*37da2899SCharles.Forsyth 0x40 ) 106*37da2899SCharles.Forsyth - 107*37da2899SCharles.Forsyth FT_MulDiv( cur->y - prev->y, /* in.y */ 108*37da2899SCharles.Forsyth next->x - cur->x, /* out.x */ 109*37da2899SCharles.Forsyth 0x40 ); 110*37da2899SCharles.Forsyth 111*37da2899SCharles.Forsyth if ( product ) 112*37da2899SCharles.Forsyth product = product > 0 ? 1 : -1; 113*37da2899SCharles.Forsyth 114*37da2899SCharles.Forsyth return product; 115*37da2899SCharles.Forsyth } 116*37da2899SCharles.Forsyth 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth /* Compute the orientation of path filling. It differs between TrueType */ 119*37da2899SCharles.Forsyth /* and Type1 formats. We could use the `FT_OUTLINE_REVERSE_FILL' flag, */ 120*37da2899SCharles.Forsyth /* but it is better to re-compute it directly (it seems that this flag */ 121*37da2899SCharles.Forsyth /* isn't correctly set for some weird composite glyphs currently). */ 122*37da2899SCharles.Forsyth /* */ 123*37da2899SCharles.Forsyth /* We do this by computing bounding box points, and computing their */ 124*37da2899SCharles.Forsyth /* curvature. */ 125*37da2899SCharles.Forsyth /* */ 126*37da2899SCharles.Forsyth /* The function returns either 1 or -1. */ 127*37da2899SCharles.Forsyth /* */ 128*37da2899SCharles.Forsyth static int ft_get_orientation(FT_Outline * outline)129*37da2899SCharles.Forsyth ft_get_orientation( FT_Outline* outline ) 130*37da2899SCharles.Forsyth { 131*37da2899SCharles.Forsyth FT_BBox box; 132*37da2899SCharles.Forsyth FT_BBox indices; 133*37da2899SCharles.Forsyth int n, last; 134*37da2899SCharles.Forsyth 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth indices.xMin = -1; 137*37da2899SCharles.Forsyth indices.yMin = -1; 138*37da2899SCharles.Forsyth indices.xMax = -1; 139*37da2899SCharles.Forsyth indices.yMax = -1; 140*37da2899SCharles.Forsyth 141*37da2899SCharles.Forsyth box.xMin = box.yMin = 32767; 142*37da2899SCharles.Forsyth box.xMax = box.yMax = -32768; 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth /* is it empty ? */ 145*37da2899SCharles.Forsyth if ( outline->n_contours < 1 ) 146*37da2899SCharles.Forsyth return 1; 147*37da2899SCharles.Forsyth 148*37da2899SCharles.Forsyth last = outline->contours[outline->n_contours - 1]; 149*37da2899SCharles.Forsyth 150*37da2899SCharles.Forsyth for ( n = 0; n <= last; n++ ) 151*37da2899SCharles.Forsyth { 152*37da2899SCharles.Forsyth FT_Pos x, y; 153*37da2899SCharles.Forsyth 154*37da2899SCharles.Forsyth 155*37da2899SCharles.Forsyth x = outline->points[n].x; 156*37da2899SCharles.Forsyth if ( x < box.xMin ) 157*37da2899SCharles.Forsyth { 158*37da2899SCharles.Forsyth box.xMin = x; 159*37da2899SCharles.Forsyth indices.xMin = n; 160*37da2899SCharles.Forsyth } 161*37da2899SCharles.Forsyth if ( x > box.xMax ) 162*37da2899SCharles.Forsyth { 163*37da2899SCharles.Forsyth box.xMax = x; 164*37da2899SCharles.Forsyth indices.xMax = n; 165*37da2899SCharles.Forsyth } 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsyth y = outline->points[n].y; 168*37da2899SCharles.Forsyth if ( y < box.yMin ) 169*37da2899SCharles.Forsyth { 170*37da2899SCharles.Forsyth box.yMin = y; 171*37da2899SCharles.Forsyth indices.yMin = n; 172*37da2899SCharles.Forsyth } 173*37da2899SCharles.Forsyth if ( y > box.yMax ) 174*37da2899SCharles.Forsyth { 175*37da2899SCharles.Forsyth box.yMax = y; 176*37da2899SCharles.Forsyth indices.yMax = n; 177*37da2899SCharles.Forsyth } 178*37da2899SCharles.Forsyth } 179*37da2899SCharles.Forsyth 180*37da2899SCharles.Forsyth /* test orientation of the xmin */ 181*37da2899SCharles.Forsyth n = ft_test_extrema( outline, indices.xMin ); 182*37da2899SCharles.Forsyth if ( n ) 183*37da2899SCharles.Forsyth goto Exit; 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth n = ft_test_extrema( outline, indices.yMin ); 186*37da2899SCharles.Forsyth if ( n ) 187*37da2899SCharles.Forsyth goto Exit; 188*37da2899SCharles.Forsyth 189*37da2899SCharles.Forsyth n = ft_test_extrema( outline, indices.xMax ); 190*37da2899SCharles.Forsyth if ( n ) 191*37da2899SCharles.Forsyth goto Exit; 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth n = ft_test_extrema( outline, indices.yMax ); 194*37da2899SCharles.Forsyth if ( !n ) 195*37da2899SCharles.Forsyth n = 1; 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth Exit: 198*37da2899SCharles.Forsyth return n; 199*37da2899SCharles.Forsyth } 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_GlyphSlot_Embolden(FT_GlyphSlot slot)203*37da2899SCharles.Forsyth FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) 204*37da2899SCharles.Forsyth { 205*37da2899SCharles.Forsyth FT_Vector* points; 206*37da2899SCharles.Forsyth FT_Vector v_prev, v_first, v_next, v_cur; 207*37da2899SCharles.Forsyth FT_Pos distance; 208*37da2899SCharles.Forsyth FT_Outline* outline = &slot->outline; 209*37da2899SCharles.Forsyth FT_Face face = FT_SLOT_FACE( slot ); 210*37da2899SCharles.Forsyth FT_Angle rotate, angle_in, angle_out; 211*37da2899SCharles.Forsyth FT_Int c, n, first, orientation; 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth /* only embolden outline glyph images */ 215*37da2899SCharles.Forsyth if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) 216*37da2899SCharles.Forsyth return; 217*37da2899SCharles.Forsyth 218*37da2899SCharles.Forsyth /* compute control distance */ 219*37da2899SCharles.Forsyth distance = FT_MulFix( face->units_per_EM / 60, 220*37da2899SCharles.Forsyth face->size->metrics.y_scale ); 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth orientation = ft_get_orientation( outline ); 223*37da2899SCharles.Forsyth rotate = FT_ANGLE_PI2*orientation; 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth points = outline->points; 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth first = 0; 228*37da2899SCharles.Forsyth for ( c = 0; c < outline->n_contours; c++ ) 229*37da2899SCharles.Forsyth { 230*37da2899SCharles.Forsyth int last = outline->contours[c]; 231*37da2899SCharles.Forsyth 232*37da2899SCharles.Forsyth 233*37da2899SCharles.Forsyth v_first = points[first]; 234*37da2899SCharles.Forsyth v_prev = points[last]; 235*37da2899SCharles.Forsyth v_cur = v_first; 236*37da2899SCharles.Forsyth 237*37da2899SCharles.Forsyth for ( n = first; n <= last; n++ ) 238*37da2899SCharles.Forsyth { 239*37da2899SCharles.Forsyth FT_Pos d; 240*37da2899SCharles.Forsyth FT_Vector in, out; 241*37da2899SCharles.Forsyth FT_Fixed scale; 242*37da2899SCharles.Forsyth FT_Angle angle_diff; 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth 245*37da2899SCharles.Forsyth if ( n < last ) v_next = points[n + 1]; 246*37da2899SCharles.Forsyth else v_next = v_first; 247*37da2899SCharles.Forsyth 248*37da2899SCharles.Forsyth /* compute the in and out vectors */ 249*37da2899SCharles.Forsyth in.x = v_cur.x - v_prev.x; 250*37da2899SCharles.Forsyth in.y = v_cur.y - v_prev.y; 251*37da2899SCharles.Forsyth 252*37da2899SCharles.Forsyth out.x = v_next.x - v_cur.x; 253*37da2899SCharles.Forsyth out.y = v_next.y - v_cur.y; 254*37da2899SCharles.Forsyth 255*37da2899SCharles.Forsyth angle_in = FT_Atan2( in.x, in.y ); 256*37da2899SCharles.Forsyth angle_out = FT_Atan2( out.x, out.y ); 257*37da2899SCharles.Forsyth angle_diff = FT_Angle_Diff( angle_in, angle_out ); 258*37da2899SCharles.Forsyth scale = FT_Cos( angle_diff/2 ); 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth if ( scale < 0x400L && scale > -0x400L ) 261*37da2899SCharles.Forsyth { 262*37da2899SCharles.Forsyth if ( scale >= 0 ) 263*37da2899SCharles.Forsyth scale = 0x400L; 264*37da2899SCharles.Forsyth else 265*37da2899SCharles.Forsyth scale = -0x400L; 266*37da2899SCharles.Forsyth } 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth d = FT_DivFix( distance, scale ); 269*37da2899SCharles.Forsyth 270*37da2899SCharles.Forsyth FT_Vector_From_Polar( &in, d, angle_in + angle_diff/2 - rotate ); 271*37da2899SCharles.Forsyth 272*37da2899SCharles.Forsyth outline->points[n].x = v_cur.x + distance + in.x; 273*37da2899SCharles.Forsyth outline->points[n].y = v_cur.y + distance + in.y; 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth v_prev = v_cur; 276*37da2899SCharles.Forsyth v_cur = v_next; 277*37da2899SCharles.Forsyth } 278*37da2899SCharles.Forsyth 279*37da2899SCharles.Forsyth first = last + 1; 280*37da2899SCharles.Forsyth } 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + distance*4 ) & -64; 283*37da2899SCharles.Forsyth } 284*37da2899SCharles.Forsyth 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth /* END */ 287