1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftoutln.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType outline management (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 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 /*************************************************************************/ 20*37da2899SCharles.Forsyth /* */ 21*37da2899SCharles.Forsyth /* All functions are declared in freetype.h. */ 22*37da2899SCharles.Forsyth /* */ 23*37da2899SCharles.Forsyth /*************************************************************************/ 24*37da2899SCharles.Forsyth 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth #include <ft2build.h> 27*37da2899SCharles.Forsyth #include FT_OUTLINE_H 28*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth 31*37da2899SCharles.Forsyth /*************************************************************************/ 32*37da2899SCharles.Forsyth /* */ 33*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 34*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 35*37da2899SCharles.Forsyth /* messages during execution. */ 36*37da2899SCharles.Forsyth /* */ 37*37da2899SCharles.Forsyth #undef FT_COMPONENT 38*37da2899SCharles.Forsyth #define FT_COMPONENT trace_outline 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsyth static 42*37da2899SCharles.Forsyth const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Decompose(FT_Outline * outline,const FT_Outline_Funcs * func_interface,void * user)48*37da2899SCharles.Forsyth FT_Outline_Decompose( FT_Outline* outline, 49*37da2899SCharles.Forsyth const FT_Outline_Funcs* func_interface, 50*37da2899SCharles.Forsyth void* user ) 51*37da2899SCharles.Forsyth { 52*37da2899SCharles.Forsyth #undef SCALED 53*37da2899SCharles.Forsyth #define SCALED( x ) ( ( (x) << shift ) - delta ) 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth FT_Vector v_last; 56*37da2899SCharles.Forsyth FT_Vector v_control; 57*37da2899SCharles.Forsyth FT_Vector v_start; 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth FT_Vector* point; 60*37da2899SCharles.Forsyth FT_Vector* limit; 61*37da2899SCharles.Forsyth char* tags; 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth FT_Error error; 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth FT_Int n; /* index of contour in outline */ 66*37da2899SCharles.Forsyth FT_UInt first; /* index of first point in contour */ 67*37da2899SCharles.Forsyth FT_Int tag; /* current point's state */ 68*37da2899SCharles.Forsyth 69*37da2899SCharles.Forsyth FT_Int shift; 70*37da2899SCharles.Forsyth FT_Pos delta; 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth 73*37da2899SCharles.Forsyth if ( !outline || !func_interface ) 74*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth shift = func_interface->shift; 77*37da2899SCharles.Forsyth delta = func_interface->delta; 78*37da2899SCharles.Forsyth first = 0; 79*37da2899SCharles.Forsyth 80*37da2899SCharles.Forsyth for ( n = 0; n < outline->n_contours; n++ ) 81*37da2899SCharles.Forsyth { 82*37da2899SCharles.Forsyth FT_Int last; /* index of last point in contour */ 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth last = outline->contours[n]; 86*37da2899SCharles.Forsyth limit = outline->points + last; 87*37da2899SCharles.Forsyth 88*37da2899SCharles.Forsyth v_start = outline->points[first]; 89*37da2899SCharles.Forsyth v_last = outline->points[last]; 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsyth v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); 92*37da2899SCharles.Forsyth v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); 93*37da2899SCharles.Forsyth 94*37da2899SCharles.Forsyth v_control = v_start; 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth point = outline->points + first; 97*37da2899SCharles.Forsyth tags = outline->tags + first; 98*37da2899SCharles.Forsyth tag = FT_CURVE_TAG( tags[0] ); 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth /* A contour cannot start with a cubic control point! */ 101*37da2899SCharles.Forsyth if ( tag == FT_CURVE_TAG_CUBIC ) 102*37da2899SCharles.Forsyth goto Invalid_Outline; 103*37da2899SCharles.Forsyth 104*37da2899SCharles.Forsyth /* check first point to determine origin */ 105*37da2899SCharles.Forsyth if ( tag == FT_CURVE_TAG_CONIC ) 106*37da2899SCharles.Forsyth { 107*37da2899SCharles.Forsyth /* first point is conic control. Yes, this happens. */ 108*37da2899SCharles.Forsyth if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 109*37da2899SCharles.Forsyth { 110*37da2899SCharles.Forsyth /* start at last point if it is on the curve */ 111*37da2899SCharles.Forsyth v_start = v_last; 112*37da2899SCharles.Forsyth limit--; 113*37da2899SCharles.Forsyth } 114*37da2899SCharles.Forsyth else 115*37da2899SCharles.Forsyth { 116*37da2899SCharles.Forsyth /* if both first and last points are conic, */ 117*37da2899SCharles.Forsyth /* start at their middle and record its position */ 118*37da2899SCharles.Forsyth /* for closure */ 119*37da2899SCharles.Forsyth v_start.x = ( v_start.x + v_last.x ) / 2; 120*37da2899SCharles.Forsyth v_start.y = ( v_start.y + v_last.y ) / 2; 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth v_last = v_start; 123*37da2899SCharles.Forsyth } 124*37da2899SCharles.Forsyth point--; 125*37da2899SCharles.Forsyth tags--; 126*37da2899SCharles.Forsyth } 127*37da2899SCharles.Forsyth 128*37da2899SCharles.Forsyth error = func_interface->move_to( &v_start, user ); 129*37da2899SCharles.Forsyth if ( error ) 130*37da2899SCharles.Forsyth goto Exit; 131*37da2899SCharles.Forsyth 132*37da2899SCharles.Forsyth while ( point < limit ) 133*37da2899SCharles.Forsyth { 134*37da2899SCharles.Forsyth point++; 135*37da2899SCharles.Forsyth tags++; 136*37da2899SCharles.Forsyth 137*37da2899SCharles.Forsyth tag = FT_CURVE_TAG( tags[0] ); 138*37da2899SCharles.Forsyth switch ( tag ) 139*37da2899SCharles.Forsyth { 140*37da2899SCharles.Forsyth case FT_CURVE_TAG_ON: /* emit a single line_to */ 141*37da2899SCharles.Forsyth { 142*37da2899SCharles.Forsyth FT_Vector vec; 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsyth vec.x = SCALED( point->x ); 146*37da2899SCharles.Forsyth vec.y = SCALED( point->y ); 147*37da2899SCharles.Forsyth 148*37da2899SCharles.Forsyth error = func_interface->line_to( &vec, user ); 149*37da2899SCharles.Forsyth if ( error ) 150*37da2899SCharles.Forsyth goto Exit; 151*37da2899SCharles.Forsyth continue; 152*37da2899SCharles.Forsyth } 153*37da2899SCharles.Forsyth 154*37da2899SCharles.Forsyth case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 155*37da2899SCharles.Forsyth v_control.x = SCALED( point->x ); 156*37da2899SCharles.Forsyth v_control.y = SCALED( point->y ); 157*37da2899SCharles.Forsyth 158*37da2899SCharles.Forsyth Do_Conic: 159*37da2899SCharles.Forsyth if ( point < limit ) 160*37da2899SCharles.Forsyth { 161*37da2899SCharles.Forsyth FT_Vector vec; 162*37da2899SCharles.Forsyth FT_Vector v_middle; 163*37da2899SCharles.Forsyth 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth point++; 166*37da2899SCharles.Forsyth tags++; 167*37da2899SCharles.Forsyth tag = FT_CURVE_TAG( tags[0] ); 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth vec.x = SCALED( point->x ); 170*37da2899SCharles.Forsyth vec.y = SCALED( point->y ); 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth if ( tag == FT_CURVE_TAG_ON ) 173*37da2899SCharles.Forsyth { 174*37da2899SCharles.Forsyth error = func_interface->conic_to( &v_control, &vec, user ); 175*37da2899SCharles.Forsyth if ( error ) 176*37da2899SCharles.Forsyth goto Exit; 177*37da2899SCharles.Forsyth continue; 178*37da2899SCharles.Forsyth } 179*37da2899SCharles.Forsyth 180*37da2899SCharles.Forsyth if ( tag != FT_CURVE_TAG_CONIC ) 181*37da2899SCharles.Forsyth goto Invalid_Outline; 182*37da2899SCharles.Forsyth 183*37da2899SCharles.Forsyth v_middle.x = ( v_control.x + vec.x ) / 2; 184*37da2899SCharles.Forsyth v_middle.y = ( v_control.y + vec.y ) / 2; 185*37da2899SCharles.Forsyth 186*37da2899SCharles.Forsyth error = func_interface->conic_to( &v_control, &v_middle, user ); 187*37da2899SCharles.Forsyth if ( error ) 188*37da2899SCharles.Forsyth goto Exit; 189*37da2899SCharles.Forsyth 190*37da2899SCharles.Forsyth v_control = vec; 191*37da2899SCharles.Forsyth goto Do_Conic; 192*37da2899SCharles.Forsyth } 193*37da2899SCharles.Forsyth 194*37da2899SCharles.Forsyth error = func_interface->conic_to( &v_control, &v_start, user ); 195*37da2899SCharles.Forsyth goto Close; 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth default: /* FT_CURVE_TAG_CUBIC */ 198*37da2899SCharles.Forsyth { 199*37da2899SCharles.Forsyth FT_Vector vec1, vec2; 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth if ( point + 1 > limit || 203*37da2899SCharles.Forsyth FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 204*37da2899SCharles.Forsyth goto Invalid_Outline; 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsyth point += 2; 207*37da2899SCharles.Forsyth tags += 2; 208*37da2899SCharles.Forsyth 209*37da2899SCharles.Forsyth vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); 210*37da2899SCharles.Forsyth vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); 211*37da2899SCharles.Forsyth 212*37da2899SCharles.Forsyth if ( point <= limit ) 213*37da2899SCharles.Forsyth { 214*37da2899SCharles.Forsyth FT_Vector vec; 215*37da2899SCharles.Forsyth 216*37da2899SCharles.Forsyth 217*37da2899SCharles.Forsyth vec.x = SCALED( point->x ); 218*37da2899SCharles.Forsyth vec.y = SCALED( point->y ); 219*37da2899SCharles.Forsyth 220*37da2899SCharles.Forsyth error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); 221*37da2899SCharles.Forsyth if ( error ) 222*37da2899SCharles.Forsyth goto Exit; 223*37da2899SCharles.Forsyth continue; 224*37da2899SCharles.Forsyth } 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsyth error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); 227*37da2899SCharles.Forsyth goto Close; 228*37da2899SCharles.Forsyth } 229*37da2899SCharles.Forsyth } 230*37da2899SCharles.Forsyth } 231*37da2899SCharles.Forsyth 232*37da2899SCharles.Forsyth /* close the contour with a line segment */ 233*37da2899SCharles.Forsyth error = func_interface->line_to( &v_start, user ); 234*37da2899SCharles.Forsyth 235*37da2899SCharles.Forsyth Close: 236*37da2899SCharles.Forsyth if ( error ) 237*37da2899SCharles.Forsyth goto Exit; 238*37da2899SCharles.Forsyth 239*37da2899SCharles.Forsyth first = last + 1; 240*37da2899SCharles.Forsyth } 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth return 0; 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth Exit: 245*37da2899SCharles.Forsyth return error; 246*37da2899SCharles.Forsyth 247*37da2899SCharles.Forsyth Invalid_Outline: 248*37da2899SCharles.Forsyth return FT_Err_Invalid_Outline; 249*37da2899SCharles.Forsyth } 250*37da2899SCharles.Forsyth 251*37da2899SCharles.Forsyth 252*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_New_Internal(FT_Memory memory,FT_UInt numPoints,FT_Int numContours,FT_Outline * anoutline)253*37da2899SCharles.Forsyth FT_Outline_New_Internal( FT_Memory memory, 254*37da2899SCharles.Forsyth FT_UInt numPoints, 255*37da2899SCharles.Forsyth FT_Int numContours, 256*37da2899SCharles.Forsyth FT_Outline *anoutline ) 257*37da2899SCharles.Forsyth { 258*37da2899SCharles.Forsyth FT_Error error; 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth 261*37da2899SCharles.Forsyth if ( !anoutline || !memory ) 262*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 263*37da2899SCharles.Forsyth 264*37da2899SCharles.Forsyth *anoutline = null_outline; 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( anoutline->points, numPoints * 2L ) || 267*37da2899SCharles.Forsyth FT_NEW_ARRAY( anoutline->tags, numPoints ) || 268*37da2899SCharles.Forsyth FT_NEW_ARRAY( anoutline->contours, numContours ) ) 269*37da2899SCharles.Forsyth goto Fail; 270*37da2899SCharles.Forsyth 271*37da2899SCharles.Forsyth anoutline->n_points = (FT_UShort)numPoints; 272*37da2899SCharles.Forsyth anoutline->n_contours = (FT_Short)numContours; 273*37da2899SCharles.Forsyth anoutline->flags |= FT_OUTLINE_OWNER; 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth return FT_Err_Ok; 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth Fail: 278*37da2899SCharles.Forsyth anoutline->flags |= FT_OUTLINE_OWNER; 279*37da2899SCharles.Forsyth FT_Outline_Done_Internal( memory, anoutline ); 280*37da2899SCharles.Forsyth 281*37da2899SCharles.Forsyth return error; 282*37da2899SCharles.Forsyth } 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsyth 285*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_New(FT_Library library,FT_UInt numPoints,FT_Int numContours,FT_Outline * anoutline)288*37da2899SCharles.Forsyth FT_Outline_New( FT_Library library, 289*37da2899SCharles.Forsyth FT_UInt numPoints, 290*37da2899SCharles.Forsyth FT_Int numContours, 291*37da2899SCharles.Forsyth FT_Outline *anoutline ) 292*37da2899SCharles.Forsyth { 293*37da2899SCharles.Forsyth if ( !library ) 294*37da2899SCharles.Forsyth return FT_Err_Invalid_Library_Handle; 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth return FT_Outline_New_Internal( library->memory, numPoints, 297*37da2899SCharles.Forsyth numContours, anoutline ); 298*37da2899SCharles.Forsyth } 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Check(FT_Outline * outline)304*37da2899SCharles.Forsyth FT_Outline_Check( FT_Outline* outline ) 305*37da2899SCharles.Forsyth { 306*37da2899SCharles.Forsyth if ( outline ) 307*37da2899SCharles.Forsyth { 308*37da2899SCharles.Forsyth FT_Int n_points = outline->n_points; 309*37da2899SCharles.Forsyth FT_Int n_contours = outline->n_contours; 310*37da2899SCharles.Forsyth FT_Int end0, end; 311*37da2899SCharles.Forsyth FT_Int n; 312*37da2899SCharles.Forsyth 313*37da2899SCharles.Forsyth 314*37da2899SCharles.Forsyth /* empty glyph? */ 315*37da2899SCharles.Forsyth if ( n_points == 0 && n_contours == 0 ) 316*37da2899SCharles.Forsyth return 0; 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth /* check point and contour counts */ 319*37da2899SCharles.Forsyth if ( n_points <= 0 || n_contours <= 0 ) 320*37da2899SCharles.Forsyth goto Bad; 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsyth end0 = end = -1; 323*37da2899SCharles.Forsyth for ( n = 0; n < n_contours; n++ ) 324*37da2899SCharles.Forsyth { 325*37da2899SCharles.Forsyth end = outline->contours[n]; 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth /* note that we don't accept empty contours */ 328*37da2899SCharles.Forsyth if ( end <= end0 || end >= n_points ) 329*37da2899SCharles.Forsyth goto Bad; 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth end0 = end; 332*37da2899SCharles.Forsyth } 333*37da2899SCharles.Forsyth 334*37da2899SCharles.Forsyth if ( end != n_points - 1 ) 335*37da2899SCharles.Forsyth goto Bad; 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth /* XXX: check the tags array */ 338*37da2899SCharles.Forsyth return 0; 339*37da2899SCharles.Forsyth } 340*37da2899SCharles.Forsyth 341*37da2899SCharles.Forsyth Bad: 342*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 343*37da2899SCharles.Forsyth } 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 347*37da2899SCharles.Forsyth 348*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Copy(FT_Outline * source,FT_Outline * target)349*37da2899SCharles.Forsyth FT_Outline_Copy( FT_Outline* source, 350*37da2899SCharles.Forsyth FT_Outline *target ) 351*37da2899SCharles.Forsyth { 352*37da2899SCharles.Forsyth FT_Int is_owner; 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth if ( !source || !target || 356*37da2899SCharles.Forsyth source->n_points != target->n_points || 357*37da2899SCharles.Forsyth source->n_contours != target->n_contours ) 358*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 359*37da2899SCharles.Forsyth 360*37da2899SCharles.Forsyth FT_MEM_COPY( target->points, source->points, 361*37da2899SCharles.Forsyth source->n_points * sizeof ( FT_Vector ) ); 362*37da2899SCharles.Forsyth 363*37da2899SCharles.Forsyth FT_MEM_COPY( target->tags, source->tags, 364*37da2899SCharles.Forsyth source->n_points * sizeof ( FT_Byte ) ); 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth FT_MEM_COPY( target->contours, source->contours, 367*37da2899SCharles.Forsyth source->n_contours * sizeof ( FT_Short ) ); 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsyth /* copy all flags, except the `FT_OUTLINE_OWNER' one */ 370*37da2899SCharles.Forsyth is_owner = target->flags & FT_OUTLINE_OWNER; 371*37da2899SCharles.Forsyth target->flags = source->flags; 372*37da2899SCharles.Forsyth 373*37da2899SCharles.Forsyth target->flags &= ~FT_OUTLINE_OWNER; 374*37da2899SCharles.Forsyth target->flags |= is_owner; 375*37da2899SCharles.Forsyth 376*37da2899SCharles.Forsyth return FT_Err_Ok; 377*37da2899SCharles.Forsyth } 378*37da2899SCharles.Forsyth 379*37da2899SCharles.Forsyth 380*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Done_Internal(FT_Memory memory,FT_Outline * outline)381*37da2899SCharles.Forsyth FT_Outline_Done_Internal( FT_Memory memory, 382*37da2899SCharles.Forsyth FT_Outline* outline ) 383*37da2899SCharles.Forsyth { 384*37da2899SCharles.Forsyth if ( outline ) 385*37da2899SCharles.Forsyth { 386*37da2899SCharles.Forsyth if ( outline->flags & FT_OUTLINE_OWNER ) 387*37da2899SCharles.Forsyth { 388*37da2899SCharles.Forsyth FT_FREE( outline->points ); 389*37da2899SCharles.Forsyth FT_FREE( outline->tags ); 390*37da2899SCharles.Forsyth FT_FREE( outline->contours ); 391*37da2899SCharles.Forsyth } 392*37da2899SCharles.Forsyth *outline = null_outline; 393*37da2899SCharles.Forsyth 394*37da2899SCharles.Forsyth return FT_Err_Ok; 395*37da2899SCharles.Forsyth } 396*37da2899SCharles.Forsyth else 397*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 398*37da2899SCharles.Forsyth } 399*37da2899SCharles.Forsyth 400*37da2899SCharles.Forsyth 401*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Done(FT_Library library,FT_Outline * outline)404*37da2899SCharles.Forsyth FT_Outline_Done( FT_Library library, 405*37da2899SCharles.Forsyth FT_Outline* outline ) 406*37da2899SCharles.Forsyth { 407*37da2899SCharles.Forsyth /* check for valid `outline' in FT_Outline_Done_Internal() */ 408*37da2899SCharles.Forsyth 409*37da2899SCharles.Forsyth if ( !library ) 410*37da2899SCharles.Forsyth return FT_Err_Invalid_Library_Handle; 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth return FT_Outline_Done_Internal( library->memory, outline ); 413*37da2899SCharles.Forsyth } 414*37da2899SCharles.Forsyth 415*37da2899SCharles.Forsyth 416*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 417*37da2899SCharles.Forsyth 418*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_Outline_Get_CBox(FT_Outline * outline,FT_BBox * acbox)419*37da2899SCharles.Forsyth FT_Outline_Get_CBox( FT_Outline* outline, 420*37da2899SCharles.Forsyth FT_BBox *acbox ) 421*37da2899SCharles.Forsyth { 422*37da2899SCharles.Forsyth FT_Pos xMin, yMin, xMax, yMax; 423*37da2899SCharles.Forsyth 424*37da2899SCharles.Forsyth 425*37da2899SCharles.Forsyth if ( outline && acbox ) 426*37da2899SCharles.Forsyth { 427*37da2899SCharles.Forsyth if ( outline->n_points == 0 ) 428*37da2899SCharles.Forsyth { 429*37da2899SCharles.Forsyth xMin = 0; 430*37da2899SCharles.Forsyth yMin = 0; 431*37da2899SCharles.Forsyth xMax = 0; 432*37da2899SCharles.Forsyth yMax = 0; 433*37da2899SCharles.Forsyth } 434*37da2899SCharles.Forsyth else 435*37da2899SCharles.Forsyth { 436*37da2899SCharles.Forsyth FT_Vector* vec = outline->points; 437*37da2899SCharles.Forsyth FT_Vector* limit = vec + outline->n_points; 438*37da2899SCharles.Forsyth 439*37da2899SCharles.Forsyth 440*37da2899SCharles.Forsyth xMin = xMax = vec->x; 441*37da2899SCharles.Forsyth yMin = yMax = vec->y; 442*37da2899SCharles.Forsyth vec++; 443*37da2899SCharles.Forsyth 444*37da2899SCharles.Forsyth for ( ; vec < limit; vec++ ) 445*37da2899SCharles.Forsyth { 446*37da2899SCharles.Forsyth FT_Pos x, y; 447*37da2899SCharles.Forsyth 448*37da2899SCharles.Forsyth 449*37da2899SCharles.Forsyth x = vec->x; 450*37da2899SCharles.Forsyth if ( x < xMin ) xMin = x; 451*37da2899SCharles.Forsyth if ( x > xMax ) xMax = x; 452*37da2899SCharles.Forsyth 453*37da2899SCharles.Forsyth y = vec->y; 454*37da2899SCharles.Forsyth if ( y < yMin ) yMin = y; 455*37da2899SCharles.Forsyth if ( y > yMax ) yMax = y; 456*37da2899SCharles.Forsyth } 457*37da2899SCharles.Forsyth } 458*37da2899SCharles.Forsyth acbox->xMin = xMin; 459*37da2899SCharles.Forsyth acbox->xMax = xMax; 460*37da2899SCharles.Forsyth acbox->yMin = yMin; 461*37da2899SCharles.Forsyth acbox->yMax = yMax; 462*37da2899SCharles.Forsyth } 463*37da2899SCharles.Forsyth } 464*37da2899SCharles.Forsyth 465*37da2899SCharles.Forsyth 466*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_Outline_Translate(FT_Outline * outline,FT_Pos xOffset,FT_Pos yOffset)469*37da2899SCharles.Forsyth FT_Outline_Translate( FT_Outline* outline, 470*37da2899SCharles.Forsyth FT_Pos xOffset, 471*37da2899SCharles.Forsyth FT_Pos yOffset ) 472*37da2899SCharles.Forsyth { 473*37da2899SCharles.Forsyth FT_UShort n; 474*37da2899SCharles.Forsyth FT_Vector* vec = outline->points; 475*37da2899SCharles.Forsyth 476*37da2899SCharles.Forsyth 477*37da2899SCharles.Forsyth for ( n = 0; n < outline->n_points; n++ ) 478*37da2899SCharles.Forsyth { 479*37da2899SCharles.Forsyth vec->x += xOffset; 480*37da2899SCharles.Forsyth vec->y += yOffset; 481*37da2899SCharles.Forsyth vec++; 482*37da2899SCharles.Forsyth } 483*37da2899SCharles.Forsyth } 484*37da2899SCharles.Forsyth 485*37da2899SCharles.Forsyth 486*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 487*37da2899SCharles.Forsyth 488*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_Outline_Reverse(FT_Outline * outline)489*37da2899SCharles.Forsyth FT_Outline_Reverse( FT_Outline* outline ) 490*37da2899SCharles.Forsyth { 491*37da2899SCharles.Forsyth FT_UShort n; 492*37da2899SCharles.Forsyth FT_Int first, last; 493*37da2899SCharles.Forsyth 494*37da2899SCharles.Forsyth 495*37da2899SCharles.Forsyth first = 0; 496*37da2899SCharles.Forsyth 497*37da2899SCharles.Forsyth for ( n = 0; n < outline->n_contours; n++ ) 498*37da2899SCharles.Forsyth { 499*37da2899SCharles.Forsyth last = outline->contours[n]; 500*37da2899SCharles.Forsyth 501*37da2899SCharles.Forsyth /* reverse point table */ 502*37da2899SCharles.Forsyth { 503*37da2899SCharles.Forsyth FT_Vector* p = outline->points + first; 504*37da2899SCharles.Forsyth FT_Vector* q = outline->points + last; 505*37da2899SCharles.Forsyth FT_Vector swap; 506*37da2899SCharles.Forsyth 507*37da2899SCharles.Forsyth 508*37da2899SCharles.Forsyth while ( p < q ) 509*37da2899SCharles.Forsyth { 510*37da2899SCharles.Forsyth swap = *p; 511*37da2899SCharles.Forsyth *p = *q; 512*37da2899SCharles.Forsyth *q = swap; 513*37da2899SCharles.Forsyth p++; 514*37da2899SCharles.Forsyth q--; 515*37da2899SCharles.Forsyth } 516*37da2899SCharles.Forsyth } 517*37da2899SCharles.Forsyth 518*37da2899SCharles.Forsyth /* reverse tags table */ 519*37da2899SCharles.Forsyth { 520*37da2899SCharles.Forsyth char* p = outline->tags + first; 521*37da2899SCharles.Forsyth char* q = outline->tags + last; 522*37da2899SCharles.Forsyth char swap; 523*37da2899SCharles.Forsyth 524*37da2899SCharles.Forsyth 525*37da2899SCharles.Forsyth while ( p < q ) 526*37da2899SCharles.Forsyth { 527*37da2899SCharles.Forsyth swap = *p; 528*37da2899SCharles.Forsyth *p = *q; 529*37da2899SCharles.Forsyth *q = swap; 530*37da2899SCharles.Forsyth p++; 531*37da2899SCharles.Forsyth q--; 532*37da2899SCharles.Forsyth } 533*37da2899SCharles.Forsyth } 534*37da2899SCharles.Forsyth 535*37da2899SCharles.Forsyth first = last + 1; 536*37da2899SCharles.Forsyth } 537*37da2899SCharles.Forsyth 538*37da2899SCharles.Forsyth outline->flags ^= FT_OUTLINE_REVERSE_FILL; 539*37da2899SCharles.Forsyth } 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth 542*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 543*37da2899SCharles.Forsyth 544*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Render(FT_Library library,FT_Outline * outline,FT_Raster_Params * params)545*37da2899SCharles.Forsyth FT_Outline_Render( FT_Library library, 546*37da2899SCharles.Forsyth FT_Outline* outline, 547*37da2899SCharles.Forsyth FT_Raster_Params* params ) 548*37da2899SCharles.Forsyth { 549*37da2899SCharles.Forsyth FT_Error error; 550*37da2899SCharles.Forsyth FT_Bool update = 0; 551*37da2899SCharles.Forsyth FT_Renderer renderer; 552*37da2899SCharles.Forsyth FT_ListNode node; 553*37da2899SCharles.Forsyth 554*37da2899SCharles.Forsyth 555*37da2899SCharles.Forsyth if ( !library ) 556*37da2899SCharles.Forsyth return FT_Err_Invalid_Library_Handle; 557*37da2899SCharles.Forsyth 558*37da2899SCharles.Forsyth if ( !params ) 559*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 560*37da2899SCharles.Forsyth 561*37da2899SCharles.Forsyth renderer = library->cur_renderer; 562*37da2899SCharles.Forsyth node = library->renderers.head; 563*37da2899SCharles.Forsyth 564*37da2899SCharles.Forsyth params->source = (void*)outline; 565*37da2899SCharles.Forsyth 566*37da2899SCharles.Forsyth error = FT_Err_Cannot_Render_Glyph; 567*37da2899SCharles.Forsyth while ( renderer ) 568*37da2899SCharles.Forsyth { 569*37da2899SCharles.Forsyth error = renderer->raster_render( renderer->raster, params ); 570*37da2899SCharles.Forsyth if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) 571*37da2899SCharles.Forsyth break; 572*37da2899SCharles.Forsyth 573*37da2899SCharles.Forsyth /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 574*37da2899SCharles.Forsyth /* is unsupported by the current renderer for this glyph image */ 575*37da2899SCharles.Forsyth /* format */ 576*37da2899SCharles.Forsyth 577*37da2899SCharles.Forsyth /* now, look for another renderer that supports the same */ 578*37da2899SCharles.Forsyth /* format */ 579*37da2899SCharles.Forsyth renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 580*37da2899SCharles.Forsyth &node ); 581*37da2899SCharles.Forsyth update = 1; 582*37da2899SCharles.Forsyth } 583*37da2899SCharles.Forsyth 584*37da2899SCharles.Forsyth /* if we changed the current renderer for the glyph image format */ 585*37da2899SCharles.Forsyth /* we need to select it as the next current one */ 586*37da2899SCharles.Forsyth if ( !error && update && renderer ) 587*37da2899SCharles.Forsyth FT_Set_Renderer( library, renderer, 0, 0 ); 588*37da2899SCharles.Forsyth 589*37da2899SCharles.Forsyth return error; 590*37da2899SCharles.Forsyth } 591*37da2899SCharles.Forsyth 592*37da2899SCharles.Forsyth 593*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 594*37da2899SCharles.Forsyth 595*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_Outline_Get_Bitmap(FT_Library library,FT_Outline * outline,FT_Bitmap * abitmap)596*37da2899SCharles.Forsyth FT_Outline_Get_Bitmap( FT_Library library, 597*37da2899SCharles.Forsyth FT_Outline* outline, 598*37da2899SCharles.Forsyth FT_Bitmap *abitmap ) 599*37da2899SCharles.Forsyth { 600*37da2899SCharles.Forsyth FT_Raster_Params params; 601*37da2899SCharles.Forsyth 602*37da2899SCharles.Forsyth 603*37da2899SCharles.Forsyth if ( !abitmap ) 604*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 605*37da2899SCharles.Forsyth 606*37da2899SCharles.Forsyth /* other checks are delayed to FT_Outline_Render() */ 607*37da2899SCharles.Forsyth 608*37da2899SCharles.Forsyth params.target = abitmap; 609*37da2899SCharles.Forsyth params.flags = 0; 610*37da2899SCharles.Forsyth 611*37da2899SCharles.Forsyth if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || 612*37da2899SCharles.Forsyth abitmap->pixel_mode == FT_PIXEL_MODE_LCD || 613*37da2899SCharles.Forsyth abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) 614*37da2899SCharles.Forsyth params.flags |= FT_RASTER_FLAG_AA; 615*37da2899SCharles.Forsyth 616*37da2899SCharles.Forsyth return FT_Outline_Render( library, outline, ¶ms ); 617*37da2899SCharles.Forsyth } 618*37da2899SCharles.Forsyth 619*37da2899SCharles.Forsyth 620*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 621*37da2899SCharles.Forsyth 622*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_Vector_Transform(FT_Vector * vector,FT_Matrix * matrix)623*37da2899SCharles.Forsyth FT_Vector_Transform( FT_Vector* vector, 624*37da2899SCharles.Forsyth FT_Matrix* matrix ) 625*37da2899SCharles.Forsyth { 626*37da2899SCharles.Forsyth FT_Pos xz, yz; 627*37da2899SCharles.Forsyth 628*37da2899SCharles.Forsyth 629*37da2899SCharles.Forsyth if ( !vector || !matrix ) 630*37da2899SCharles.Forsyth return; 631*37da2899SCharles.Forsyth 632*37da2899SCharles.Forsyth xz = FT_MulFix( vector->x, matrix->xx ) + 633*37da2899SCharles.Forsyth FT_MulFix( vector->y, matrix->xy ); 634*37da2899SCharles.Forsyth 635*37da2899SCharles.Forsyth yz = FT_MulFix( vector->x, matrix->yx ) + 636*37da2899SCharles.Forsyth FT_MulFix( vector->y, matrix->yy ); 637*37da2899SCharles.Forsyth 638*37da2899SCharles.Forsyth vector->x = xz; 639*37da2899SCharles.Forsyth vector->y = yz; 640*37da2899SCharles.Forsyth } 641*37da2899SCharles.Forsyth 642*37da2899SCharles.Forsyth 643*37da2899SCharles.Forsyth /* documentation is in ftoutln.h */ 644*37da2899SCharles.Forsyth 645*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FT_Outline_Transform(FT_Outline * outline,FT_Matrix * matrix)646*37da2899SCharles.Forsyth FT_Outline_Transform( FT_Outline* outline, 647*37da2899SCharles.Forsyth FT_Matrix* matrix ) 648*37da2899SCharles.Forsyth { 649*37da2899SCharles.Forsyth FT_Vector* vec = outline->points; 650*37da2899SCharles.Forsyth FT_Vector* limit = vec + outline->n_points; 651*37da2899SCharles.Forsyth 652*37da2899SCharles.Forsyth 653*37da2899SCharles.Forsyth for ( ; vec < limit; vec++ ) 654*37da2899SCharles.Forsyth FT_Vector_Transform( vec, matrix ); 655*37da2899SCharles.Forsyth } 656*37da2899SCharles.Forsyth 657*37da2899SCharles.Forsyth 658*37da2899SCharles.Forsyth /* END */ 659