ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftoutln.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftoutln.c                                                              */
00004 /*                                                                         */
00005 /*    FreeType outline management (body).                                  */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019   /*************************************************************************/
00020   /*                                                                       */
00021   /* All functions are declared in freetype.h.                             */
00022   /*                                                                       */
00023   /*************************************************************************/
00024 
00025 
00026 #include <ft2build.h>
00027 #include FT_OUTLINE_H
00028 #include FT_INTERNAL_OBJECTS_H
00029 #include FT_INTERNAL_DEBUG_H
00030 #include FT_TRIGONOMETRY_H
00031 
00032 
00033   /*************************************************************************/
00034   /*                                                                       */
00035   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00036   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00037   /* messages during execution.                                            */
00038   /*                                                                       */
00039 #undef  FT_COMPONENT
00040 #define FT_COMPONENT  trace_outline
00041 
00042 
00043   static
00044   const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
00045 
00046 
00047   /* documentation is in ftoutln.h */
00048 
00049   FT_EXPORT_DEF( FT_Error )
00050   FT_Outline_Decompose( FT_Outline*              outline,
00051                         const FT_Outline_Funcs*  func_interface,
00052                         void*                    user )
00053   {
00054 #undef SCALED
00055 #define SCALED( x )  ( ( (x) << shift ) - delta )
00056 
00057     FT_Vector   v_last;
00058     FT_Vector   v_control;
00059     FT_Vector   v_start;
00060 
00061     FT_Vector*  point;
00062     FT_Vector*  limit;
00063     char*       tags;
00064 
00065     FT_Error    error;
00066 
00067     FT_Int   n;         /* index of contour in outline     */
00068     FT_UInt  first;     /* index of first point in contour */
00069     FT_Int   tag;       /* current point's state           */
00070 
00071     FT_Int   shift;
00072     FT_Pos   delta;
00073 
00074 
00075     if ( !outline || !func_interface )
00076       return FT_Err_Invalid_Argument;
00077 
00078     shift = func_interface->shift;
00079     delta = func_interface->delta;
00080     first = 0;
00081 
00082     for ( n = 0; n < outline->n_contours; n++ )
00083     {
00084       FT_Int  last;  /* index of last point in contour */
00085 
00086 
00087       FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
00088 
00089       last = outline->contours[n];
00090       if ( last < 0 )
00091         goto Invalid_Outline;
00092       limit = outline->points + last;
00093 
00094       v_start   = outline->points[first];
00095       v_start.x = SCALED( v_start.x );
00096       v_start.y = SCALED( v_start.y );
00097 
00098       v_last   = outline->points[last];
00099       v_last.x = SCALED( v_last.x );
00100       v_last.y = SCALED( v_last.y );
00101 
00102       v_control = v_start;
00103 
00104       point = outline->points + first;
00105       tags  = outline->tags   + first;
00106       tag   = FT_CURVE_TAG( tags[0] );
00107 
00108       /* A contour cannot start with a cubic control point! */
00109       if ( tag == FT_CURVE_TAG_CUBIC )
00110         goto Invalid_Outline;
00111 
00112       /* check first point to determine origin */
00113       if ( tag == FT_CURVE_TAG_CONIC )
00114       {
00115         /* first point is conic control.  Yes, this happens. */
00116         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
00117         {
00118           /* start at last point if it is on the curve */
00119           v_start = v_last;
00120           limit--;
00121         }
00122         else
00123         {
00124           /* if both first and last points are conic,         */
00125           /* start at their middle and record its position    */
00126           /* for closure                                      */
00127           v_start.x = ( v_start.x + v_last.x ) / 2;
00128           v_start.y = ( v_start.y + v_last.y ) / 2;
00129 
00130           v_last = v_start;
00131         }
00132         point--;
00133         tags--;
00134       }
00135 
00136       FT_TRACE5(( "  move to (%.2f, %.2f)\n",
00137                   v_start.x / 64.0, v_start.y / 64.0 ));
00138       error = func_interface->move_to( &v_start, user );
00139       if ( error )
00140         goto Exit;
00141 
00142       while ( point < limit )
00143       {
00144         point++;
00145         tags++;
00146 
00147         tag = FT_CURVE_TAG( tags[0] );
00148         switch ( tag )
00149         {
00150         case FT_CURVE_TAG_ON:  /* emit a single line_to */
00151           {
00152             FT_Vector  vec;
00153 
00154 
00155             vec.x = SCALED( point->x );
00156             vec.y = SCALED( point->y );
00157 
00158             FT_TRACE5(( "  line to (%.2f, %.2f)\n",
00159                         vec.x / 64.0, vec.y / 64.0 ));
00160             error = func_interface->line_to( &vec, user );
00161             if ( error )
00162               goto Exit;
00163             continue;
00164           }
00165 
00166         case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
00167           v_control.x = SCALED( point->x );
00168           v_control.y = SCALED( point->y );
00169 
00170         Do_Conic:
00171           if ( point < limit )
00172           {
00173             FT_Vector  vec;
00174             FT_Vector  v_middle;
00175 
00176 
00177             point++;
00178             tags++;
00179             tag = FT_CURVE_TAG( tags[0] );
00180 
00181             vec.x = SCALED( point->x );
00182             vec.y = SCALED( point->y );
00183 
00184             if ( tag == FT_CURVE_TAG_ON )
00185             {
00186               FT_TRACE5(( "  conic to (%.2f, %.2f)"
00187                           " with control (%.2f, %.2f)\n",
00188                           vec.x / 64.0, vec.y / 64.0,
00189                           v_control.x / 64.0, v_control.y / 64.0 ));
00190               error = func_interface->conic_to( &v_control, &vec, user );
00191               if ( error )
00192                 goto Exit;
00193               continue;
00194             }
00195 
00196             if ( tag != FT_CURVE_TAG_CONIC )
00197               goto Invalid_Outline;
00198 
00199             v_middle.x = ( v_control.x + vec.x ) / 2;
00200             v_middle.y = ( v_control.y + vec.y ) / 2;
00201 
00202             FT_TRACE5(( "  conic to (%.2f, %.2f)"
00203                         " with control (%.2f, %.2f)\n",
00204                         v_middle.x / 64.0, v_middle.y / 64.0,
00205                         v_control.x / 64.0, v_control.y / 64.0 ));
00206             error = func_interface->conic_to( &v_control, &v_middle, user );
00207             if ( error )
00208               goto Exit;
00209 
00210             v_control = vec;
00211             goto Do_Conic;
00212           }
00213 
00214           FT_TRACE5(( "  conic to (%.2f, %.2f)"
00215                       " with control (%.2f, %.2f)\n",
00216                       v_start.x / 64.0, v_start.y / 64.0,
00217                       v_control.x / 64.0, v_control.y / 64.0 ));
00218           error = func_interface->conic_to( &v_control, &v_start, user );
00219           goto Close;
00220 
00221         default:  /* FT_CURVE_TAG_CUBIC */
00222           {
00223             FT_Vector  vec1, vec2;
00224 
00225 
00226             if ( point + 1 > limit                             ||
00227                  FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
00228               goto Invalid_Outline;
00229 
00230             point += 2;
00231             tags  += 2;
00232 
00233             vec1.x = SCALED( point[-2].x );
00234             vec1.y = SCALED( point[-2].y );
00235 
00236             vec2.x = SCALED( point[-1].x );
00237             vec2.y = SCALED( point[-1].y );
00238 
00239             if ( point <= limit )
00240             {
00241               FT_Vector  vec;
00242 
00243 
00244               vec.x = SCALED( point->x );
00245               vec.y = SCALED( point->y );
00246 
00247               FT_TRACE5(( "  cubic to (%.2f, %.2f)"
00248                           " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
00249                           vec.x / 64.0, vec.y / 64.0,
00250                           vec1.x / 64.0, vec1.y / 64.0,
00251                           vec2.x / 64.0, vec2.y / 64.0 ));
00252               error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
00253               if ( error )
00254                 goto Exit;
00255               continue;
00256             }
00257 
00258             FT_TRACE5(( "  cubic to (%.2f, %.2f)"
00259                         " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
00260                         v_start.x / 64.0, v_start.y / 64.0,
00261                         vec1.x / 64.0, vec1.y / 64.0,
00262                         vec2.x / 64.0, vec2.y / 64.0 ));
00263             error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
00264             goto Close;
00265           }
00266         }
00267       }
00268 
00269       /* close the contour with a line segment */
00270       FT_TRACE5(( "  line to (%.2f, %.2f)\n",
00271                   v_start.x / 64.0, v_start.y / 64.0 ));
00272       error = func_interface->line_to( &v_start, user );
00273 
00274     Close:
00275       if ( error )
00276         goto Exit;
00277 
00278       first = last + 1;
00279     }
00280 
00281     FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
00282     return FT_Err_Ok;
00283 
00284   Exit:
00285     FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
00286     return error;
00287 
00288   Invalid_Outline:
00289     return FT_Err_Invalid_Outline;
00290   }
00291 
00292 
00293   FT_EXPORT_DEF( FT_Error )
00294   FT_Outline_New_Internal( FT_Memory    memory,
00295                            FT_UInt      numPoints,
00296                            FT_Int       numContours,
00297                            FT_Outline  *anoutline )
00298   {
00299     FT_Error  error;
00300 
00301 
00302     if ( !anoutline || !memory )
00303       return FT_Err_Invalid_Argument;
00304 
00305     *anoutline = null_outline;
00306 
00307     if ( FT_NEW_ARRAY( anoutline->points,   numPoints   ) ||
00308          FT_NEW_ARRAY( anoutline->tags,     numPoints   ) ||
00309          FT_NEW_ARRAY( anoutline->contours, numContours ) )
00310       goto Fail;
00311 
00312     anoutline->n_points    = (FT_UShort)numPoints;
00313     anoutline->n_contours  = (FT_Short)numContours;
00314     anoutline->flags      |= FT_OUTLINE_OWNER;
00315 
00316     return FT_Err_Ok;
00317 
00318   Fail:
00319     anoutline->flags |= FT_OUTLINE_OWNER;
00320     FT_Outline_Done_Internal( memory, anoutline );
00321 
00322     return error;
00323   }
00324 
00325 
00326   /* documentation is in ftoutln.h */
00327 
00328   FT_EXPORT_DEF( FT_Error )
00329   FT_Outline_New( FT_Library   library,
00330                   FT_UInt      numPoints,
00331                   FT_Int       numContours,
00332                   FT_Outline  *anoutline )
00333   {
00334     if ( !library )
00335       return FT_Err_Invalid_Library_Handle;
00336 
00337     return FT_Outline_New_Internal( library->memory, numPoints,
00338                                     numContours, anoutline );
00339   }
00340 
00341 
00342   /* documentation is in ftoutln.h */
00343 
00344   FT_EXPORT_DEF( FT_Error )
00345   FT_Outline_Check( FT_Outline*  outline )
00346   {
00347     if ( outline )
00348     {
00349       FT_Int  n_points   = outline->n_points;
00350       FT_Int  n_contours = outline->n_contours;
00351       FT_Int  end0, end;
00352       FT_Int  n;
00353 
00354 
00355       /* empty glyph? */
00356       if ( n_points == 0 && n_contours == 0 )
00357         return 0;
00358 
00359       /* check point and contour counts */
00360       if ( n_points <= 0 || n_contours <= 0 )
00361         goto Bad;
00362 
00363       end0 = end = -1;
00364       for ( n = 0; n < n_contours; n++ )
00365       {
00366         end = outline->contours[n];
00367 
00368         /* note that we don't accept empty contours */
00369         if ( end <= end0 || end >= n_points )
00370           goto Bad;
00371 
00372         end0 = end;
00373       }
00374 
00375       if ( end != n_points - 1 )
00376         goto Bad;
00377 
00378       /* XXX: check the tags array */
00379       return 0;
00380     }
00381 
00382   Bad:
00383     return FT_Err_Invalid_Argument;
00384   }
00385 
00386 
00387   /* documentation is in ftoutln.h */
00388 
00389   FT_EXPORT_DEF( FT_Error )
00390   FT_Outline_Copy( const FT_Outline*  source,
00391                    FT_Outline        *target )
00392   {
00393     FT_Int  is_owner;
00394 
00395 
00396     if ( !source            || !target            ||
00397          source->n_points   != target->n_points   ||
00398          source->n_contours != target->n_contours )
00399       return FT_Err_Invalid_Argument;
00400 
00401     if ( source == target )
00402       return FT_Err_Ok;
00403 
00404     FT_ARRAY_COPY( target->points, source->points, source->n_points );
00405 
00406     FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
00407 
00408     FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
00409 
00410     /* copy all flags, except the `FT_OUTLINE_OWNER' one */
00411     is_owner      = target->flags & FT_OUTLINE_OWNER;
00412     target->flags = source->flags;
00413 
00414     target->flags &= ~FT_OUTLINE_OWNER;
00415     target->flags |= is_owner;
00416 
00417     return FT_Err_Ok;
00418   }
00419 
00420 
00421   FT_EXPORT_DEF( FT_Error )
00422   FT_Outline_Done_Internal( FT_Memory    memory,
00423                             FT_Outline*  outline )
00424   {
00425     if ( memory && outline )
00426     {
00427       if ( outline->flags & FT_OUTLINE_OWNER )
00428       {
00429         FT_FREE( outline->points   );
00430         FT_FREE( outline->tags     );
00431         FT_FREE( outline->contours );
00432       }
00433       *outline = null_outline;
00434 
00435       return FT_Err_Ok;
00436     }
00437     else
00438       return FT_Err_Invalid_Argument;
00439   }
00440 
00441 
00442   /* documentation is in ftoutln.h */
00443 
00444   FT_EXPORT_DEF( FT_Error )
00445   FT_Outline_Done( FT_Library   library,
00446                    FT_Outline*  outline )
00447   {
00448     /* check for valid `outline' in FT_Outline_Done_Internal() */
00449 
00450     if ( !library )
00451       return FT_Err_Invalid_Library_Handle;
00452 
00453     return FT_Outline_Done_Internal( library->memory, outline );
00454   }
00455 
00456 
00457   /* documentation is in ftoutln.h */
00458 
00459   FT_EXPORT_DEF( void )
00460   FT_Outline_Get_CBox( const FT_Outline*  outline,
00461                        FT_BBox           *acbox )
00462   {
00463     FT_Pos  xMin, yMin, xMax, yMax;
00464 
00465 
00466     if ( outline && acbox )
00467     {
00468       if ( outline->n_points == 0 )
00469       {
00470         xMin = 0;
00471         yMin = 0;
00472         xMax = 0;
00473         yMax = 0;
00474       }
00475       else
00476       {
00477         FT_Vector*  vec   = outline->points;
00478         FT_Vector*  limit = vec + outline->n_points;
00479 
00480 
00481         xMin = xMax = vec->x;
00482         yMin = yMax = vec->y;
00483         vec++;
00484 
00485         for ( ; vec < limit; vec++ )
00486         {
00487           FT_Pos  x, y;
00488 
00489 
00490           x = vec->x;
00491           if ( x < xMin ) xMin = x;
00492           if ( x > xMax ) xMax = x;
00493 
00494           y = vec->y;
00495           if ( y < yMin ) yMin = y;
00496           if ( y > yMax ) yMax = y;
00497         }
00498       }
00499       acbox->xMin = xMin;
00500       acbox->xMax = xMax;
00501       acbox->yMin = yMin;
00502       acbox->yMax = yMax;
00503     }
00504   }
00505 
00506 
00507   /* documentation is in ftoutln.h */
00508 
00509   FT_EXPORT_DEF( void )
00510   FT_Outline_Translate( const FT_Outline*  outline,
00511                         FT_Pos             xOffset,
00512                         FT_Pos             yOffset )
00513   {
00514     FT_UShort   n;
00515     FT_Vector*  vec;
00516 
00517 
00518     if ( !outline )
00519       return;
00520 
00521     vec = outline->points;
00522 
00523     for ( n = 0; n < outline->n_points; n++ )
00524     {
00525       vec->x += xOffset;
00526       vec->y += yOffset;
00527       vec++;
00528     }
00529   }
00530 
00531 
00532   /* documentation is in ftoutln.h */
00533 
00534   FT_EXPORT_DEF( void )
00535   FT_Outline_Reverse( FT_Outline*  outline )
00536   {
00537     FT_UShort  n;
00538     FT_Int     first, last;
00539 
00540 
00541     if ( !outline )
00542       return;
00543 
00544     first = 0;
00545 
00546     for ( n = 0; n < outline->n_contours; n++ )
00547     {
00548       last  = outline->contours[n];
00549 
00550       /* reverse point table */
00551       {
00552         FT_Vector*  p = outline->points + first;
00553         FT_Vector*  q = outline->points + last;
00554         FT_Vector   swap;
00555 
00556 
00557         while ( p < q )
00558         {
00559           swap = *p;
00560           *p   = *q;
00561           *q   = swap;
00562           p++;
00563           q--;
00564         }
00565       }
00566 
00567       /* reverse tags table */
00568       {
00569         char*  p = outline->tags + first;
00570         char*  q = outline->tags + last;
00571         char   swap;
00572 
00573 
00574         while ( p < q )
00575         {
00576           swap = *p;
00577           *p   = *q;
00578           *q   = swap;
00579           p++;
00580           q--;
00581         }
00582       }
00583 
00584       first = last + 1;
00585     }
00586 
00587     outline->flags ^= FT_OUTLINE_REVERSE_FILL;
00588   }
00589 
00590 
00591   /* documentation is in ftoutln.h */
00592 
00593   FT_EXPORT_DEF( FT_Error )
00594   FT_Outline_Render( FT_Library         library,
00595                      FT_Outline*        outline,
00596                      FT_Raster_Params*  params )
00597   {
00598     FT_Error     error;
00599     FT_Bool      update = FALSE;
00600     FT_Renderer  renderer;
00601     FT_ListNode  node;
00602 
00603 
00604     if ( !library )
00605       return FT_Err_Invalid_Library_Handle;
00606 
00607     if ( !outline || !params )
00608       return FT_Err_Invalid_Argument;
00609 
00610     renderer = library->cur_renderer;
00611     node     = library->renderers.head;
00612 
00613     params->source = (void*)outline;
00614 
00615     error = FT_Err_Cannot_Render_Glyph;
00616     while ( renderer )
00617     {
00618       error = renderer->raster_render( renderer->raster, params );
00619       if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
00620         break;
00621 
00622       /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
00623       /* is unsupported by the current renderer for this glyph image */
00624       /* format                                                      */
00625 
00626       /* now, look for another renderer that supports the same */
00627       /* format                                                */
00628       renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
00629                                      &node );
00630       update   = TRUE;
00631     }
00632 
00633     /* if we changed the current renderer for the glyph image format */
00634     /* we need to select it as the next current one                  */
00635     if ( !error && update && renderer )
00636       FT_Set_Renderer( library, renderer, 0, 0 );
00637 
00638     return error;
00639   }
00640 
00641 
00642   /* documentation is in ftoutln.h */
00643 
00644   FT_EXPORT_DEF( FT_Error )
00645   FT_Outline_Get_Bitmap( FT_Library        library,
00646                          FT_Outline*       outline,
00647                          const FT_Bitmap  *abitmap )
00648   {
00649     FT_Raster_Params  params;
00650 
00651 
00652     if ( !abitmap )
00653       return FT_Err_Invalid_Argument;
00654 
00655     /* other checks are delayed to FT_Outline_Render() */
00656 
00657     params.target = abitmap;
00658     params.flags  = 0;
00659 
00660     if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY  ||
00661          abitmap->pixel_mode == FT_PIXEL_MODE_LCD   ||
00662          abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
00663       params.flags |= FT_RASTER_FLAG_AA;
00664 
00665     return FT_Outline_Render( library, outline, &params );
00666   }
00667 
00668 
00669   /* documentation is in freetype.h */
00670 
00671   FT_EXPORT_DEF( void )
00672   FT_Vector_Transform( FT_Vector*        vector,
00673                        const FT_Matrix*  matrix )
00674   {
00675     FT_Pos  xz, yz;
00676 
00677 
00678     if ( !vector || !matrix )
00679       return;
00680 
00681     xz = FT_MulFix( vector->x, matrix->xx ) +
00682          FT_MulFix( vector->y, matrix->xy );
00683 
00684     yz = FT_MulFix( vector->x, matrix->yx ) +
00685          FT_MulFix( vector->y, matrix->yy );
00686 
00687     vector->x = xz;
00688     vector->y = yz;
00689   }
00690 
00691 
00692   /* documentation is in ftoutln.h */
00693 
00694   FT_EXPORT_DEF( void )
00695   FT_Outline_Transform( const FT_Outline*  outline,
00696                         const FT_Matrix*   matrix )
00697   {
00698     FT_Vector*  vec;
00699     FT_Vector*  limit;
00700 
00701 
00702     if ( !outline || !matrix )
00703       return;
00704 
00705     vec   = outline->points;
00706     limit = vec + outline->n_points;
00707 
00708     for ( ; vec < limit; vec++ )
00709       FT_Vector_Transform( vec, matrix );
00710   }
00711 
00712 
00713 #if 0
00714 
00715 #define FT_OUTLINE_GET_CONTOUR( outline, c, first, last )  \
00716   do {                                                     \
00717     (first) = ( c > 0 ) ? (outline)->points +              \
00718                             (outline)->contours[c - 1] + 1 \
00719                         : (outline)->points;               \
00720     (last) = (outline)->points + (outline)->contours[c];   \
00721   } while ( 0 )
00722 
00723 
00724   /* Is a point in some contour?                     */
00725   /*                                                 */
00726   /* We treat every point of the contour as if it    */
00727   /* it were ON.  That is, we allow false positives, */
00728   /* but disallow false negatives.  (XXX really?)    */
00729   static FT_Bool
00730   ft_contour_has( FT_Outline*  outline,
00731                   FT_Short     c,
00732                   FT_Vector*   point )
00733   {
00734     FT_Vector*  first;
00735     FT_Vector*  last;
00736     FT_Vector*  a;
00737     FT_Vector*  b;
00738     FT_UInt     n = 0;
00739 
00740 
00741     FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
00742 
00743     for ( a = first; a <= last; a++ )
00744     {
00745       FT_Pos  x;
00746       FT_Int  intersect;
00747 
00748 
00749       b = ( a == last ) ? first : a + 1;
00750 
00751       intersect = ( a->y - point->y ) ^ ( b->y - point->y );
00752 
00753       /* a and b are on the same side */
00754       if ( intersect >= 0 )
00755       {
00756         if ( intersect == 0 && a->y == point->y )
00757         {
00758           if ( ( a->x <= point->x && b->x >= point->x ) ||
00759                ( a->x >= point->x && b->x <= point->x ) )
00760             return 1;
00761         }
00762 
00763         continue;
00764       }
00765 
00766       x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
00767 
00768       if ( x < point->x )
00769         n++;
00770       else if ( x == point->x )
00771         return 1;
00772     }
00773 
00774     return ( n % 2 );
00775   }
00776 
00777 
00778   static FT_Bool
00779   ft_contour_enclosed( FT_Outline*  outline,
00780                        FT_UShort    c )
00781   {
00782     FT_Vector*  first;
00783     FT_Vector*  last;
00784     FT_Short    i;
00785 
00786 
00787     FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
00788 
00789     for ( i = 0; i < outline->n_contours; i++ )
00790     {
00791       if ( i != c && ft_contour_has( outline, i, first ) )
00792       {
00793         FT_Vector*  pt;
00794 
00795 
00796         for ( pt = first + 1; pt <= last; pt++ )
00797           if ( !ft_contour_has( outline, i, pt ) )
00798             return 0;
00799 
00800         return 1;
00801       }
00802     }
00803 
00804     return 0;
00805   }
00806 
00807 
00808   /* This version differs from the public one in that each */
00809   /* part (contour not enclosed in another contour) of the */
00810   /* outline is checked for orientation.  This is          */
00811   /* necessary for some buggy CJK fonts.                   */
00812   static FT_Orientation
00813   ft_outline_get_orientation( FT_Outline*  outline )
00814   {
00815     FT_Short        i;
00816     FT_Vector*      first;
00817     FT_Vector*      last;
00818     FT_Orientation  orient = FT_ORIENTATION_NONE;
00819 
00820 
00821     first = outline->points;
00822     for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
00823     {
00824       FT_Vector*  point;
00825       FT_Vector*  xmin_point;
00826       FT_Pos      xmin;
00827 
00828 
00829       last = outline->points + outline->contours[i];
00830 
00831       /* skip degenerate contours */
00832       if ( last < first + 2 )
00833         continue;
00834 
00835       if ( ft_contour_enclosed( outline, i ) )
00836         continue;
00837 
00838       xmin       = first->x;
00839       xmin_point = first;
00840 
00841       for ( point = first + 1; point <= last; point++ )
00842       {
00843         if ( point->x < xmin )
00844         {
00845           xmin       = point->x;
00846           xmin_point = point;
00847         }
00848       }
00849 
00850       /* check the orientation of the contour */
00851       {
00852         FT_Vector*      prev;
00853         FT_Vector*      next;
00854         FT_Orientation  o;
00855 
00856 
00857         prev = ( xmin_point == first ) ? last : xmin_point - 1;
00858         next = ( xmin_point == last ) ? first : xmin_point + 1;
00859 
00860         if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
00861              FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
00862           o = FT_ORIENTATION_POSTSCRIPT;
00863         else
00864           o = FT_ORIENTATION_TRUETYPE;
00865 
00866         if ( orient == FT_ORIENTATION_NONE )
00867           orient = o;
00868         else if ( orient != o )
00869           return FT_ORIENTATION_NONE;
00870       }
00871     }
00872 
00873     return orient;
00874   }
00875 
00876 #endif /* 0 */
00877 
00878 
00879   /* documentation is in ftoutln.h */
00880 
00881   FT_EXPORT_DEF( FT_Error )
00882   FT_Outline_Embolden( FT_Outline*  outline,
00883                        FT_Pos       strength )
00884   {
00885     FT_Vector*  points;
00886     FT_Vector   v_prev, v_first, v_next, v_cur;
00887     FT_Angle    rotate, angle_in, angle_out;
00888     FT_Int      c, n, first;
00889     FT_Int      orientation;
00890 
00891 
00892     if ( !outline )
00893       return FT_Err_Invalid_Argument;
00894 
00895     strength /= 2;
00896     if ( strength == 0 )
00897       return FT_Err_Ok;
00898 
00899     orientation = FT_Outline_Get_Orientation( outline );
00900     if ( orientation == FT_ORIENTATION_NONE )
00901     {
00902       if ( outline->n_contours )
00903         return FT_Err_Invalid_Argument;
00904       else
00905         return FT_Err_Ok;
00906     }
00907 
00908     if ( orientation == FT_ORIENTATION_TRUETYPE )
00909       rotate = -FT_ANGLE_PI2;
00910     else
00911       rotate = FT_ANGLE_PI2;
00912 
00913     points = outline->points;
00914 
00915     first = 0;
00916     for ( c = 0; c < outline->n_contours; c++ )
00917     {
00918       int  last = outline->contours[c];
00919 
00920 
00921       v_first = points[first];
00922       v_prev  = points[last];
00923       v_cur   = v_first;
00924 
00925       for ( n = first; n <= last; n++ )
00926       {
00927         FT_Vector  in, out;
00928         FT_Angle   angle_diff;
00929         FT_Pos     d;
00930         FT_Fixed   scale;
00931 
00932 
00933         if ( n < last )
00934           v_next = points[n + 1];
00935         else
00936           v_next = v_first;
00937 
00938         /* compute the in and out vectors */
00939         in.x = v_cur.x - v_prev.x;
00940         in.y = v_cur.y - v_prev.y;
00941 
00942         out.x = v_next.x - v_cur.x;
00943         out.y = v_next.y - v_cur.y;
00944 
00945         angle_in   = FT_Atan2( in.x, in.y );
00946         angle_out  = FT_Atan2( out.x, out.y );
00947         angle_diff = FT_Angle_Diff( angle_in, angle_out );
00948         scale      = FT_Cos( angle_diff / 2 );
00949 
00950         if ( scale < 0x4000L && scale > -0x4000L )
00951           in.x = in.y = 0;
00952         else
00953         {
00954           d = FT_DivFix( strength, scale );
00955 
00956           FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
00957         }
00958 
00959         outline->points[n].x = v_cur.x + strength + in.x;
00960         outline->points[n].y = v_cur.y + strength + in.y;
00961 
00962         v_prev = v_cur;
00963         v_cur  = v_next;
00964       }
00965 
00966       first = last + 1;
00967     }
00968 
00969     return FT_Err_Ok;
00970   }
00971 
00972 
00973   /* documentation is in ftoutln.h */
00974 
00975   FT_EXPORT_DEF( FT_Orientation )
00976   FT_Outline_Get_Orientation( FT_Outline*  outline )
00977   {
00978     FT_Pos      xmin       = 32768L;
00979     FT_Pos      xmin_ymin  = 32768L;
00980     FT_Pos      xmin_ymax  = -32768L;
00981     FT_Vector*  xmin_first = NULL;
00982     FT_Vector*  xmin_last  = NULL;
00983 
00984     short*      contour;
00985 
00986     FT_Vector*  first;
00987     FT_Vector*  last;
00988     FT_Vector*  prev;
00989     FT_Vector*  point;
00990 
00991     int             i;
00992     FT_Pos          ray_y[3];
00993     FT_Orientation  result[3] =
00994       { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE };
00995 
00996 
00997     if ( !outline || outline->n_points <= 0 )
00998       return FT_ORIENTATION_TRUETYPE;
00999 
01000     /* We use the nonzero winding rule to find the orientation.       */
01001     /* Since glyph outlines behave much more `regular' than arbitrary */
01002     /* cubic or quadratic curves, this test deals with the polygon    */
01003     /* only which is spanned up by the control points.                */
01004 
01005     first = outline->points;
01006     for ( contour = outline->contours;
01007           contour < outline->contours + outline->n_contours;
01008           contour++, first = last + 1 )
01009     {
01010       FT_Pos  contour_xmin = 32768L;
01011       FT_Pos  contour_xmax = -32768L;
01012       FT_Pos  contour_ymin = 32768L;
01013       FT_Pos  contour_ymax = -32768L;
01014 
01015 
01016       last = outline->points + *contour;
01017 
01018       /* skip degenerate contours */
01019       if ( last < first + 2 )
01020         continue;
01021 
01022       for ( point = first; point <= last; ++point )
01023       {
01024         if ( point->x < contour_xmin )
01025           contour_xmin = point->x;
01026 
01027         if ( point->x > contour_xmax )
01028           contour_xmax = point->x;
01029 
01030         if ( point->y < contour_ymin )
01031           contour_ymin = point->y;
01032 
01033         if ( point->y > contour_ymax )
01034           contour_ymax = point->y;
01035       }
01036 
01037       if ( contour_xmin < xmin          &&
01038            contour_xmin != contour_xmax &&
01039            contour_ymin != contour_ymax )
01040       {
01041         xmin       = contour_xmin;
01042         xmin_ymin  = contour_ymin;
01043         xmin_ymax  = contour_ymax;
01044         xmin_first = first;
01045         xmin_last  = last;
01046       }
01047     }
01048 
01049     if ( xmin == 32768L )
01050       return FT_ORIENTATION_TRUETYPE;
01051 
01052     ray_y[0] = ( xmin_ymin * 3 + xmin_ymax     ) >> 2;
01053     ray_y[1] = ( xmin_ymin     + xmin_ymax     ) >> 1;
01054     ray_y[2] = ( xmin_ymin     + xmin_ymax * 3 ) >> 2;
01055 
01056     for ( i = 0; i < 3; i++ )
01057     {
01058       FT_Pos      left_x;
01059       FT_Pos      right_x;
01060       FT_Vector*  left1;
01061       FT_Vector*  left2;
01062       FT_Vector*  right1;
01063       FT_Vector*  right2;
01064 
01065 
01066     RedoRay:
01067       left_x  = 32768L;
01068       right_x = -32768L;
01069 
01070       left1 = left2 = right1 = right2 = NULL;
01071 
01072       prev = xmin_last;
01073       for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
01074       {
01075         FT_Pos  tmp_x;
01076 
01077 
01078         if ( point->y == ray_y[i] || prev->y == ray_y[i] )
01079         {
01080           ray_y[i]++;
01081           goto RedoRay;
01082         }
01083 
01084         if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||
01085              ( point->y > ray_y[i] && prev->y > ray_y[i] ) )
01086           continue;
01087 
01088         tmp_x = FT_MulDiv( point->x - prev->x,
01089                            ray_y[i] - prev->y,
01090                            point->y - prev->y ) + prev->x;
01091 
01092         if ( tmp_x < left_x )
01093         {
01094           left_x = tmp_x;
01095           left1  = prev;
01096           left2  = point;
01097         }
01098 
01099         if ( tmp_x > right_x )
01100         {
01101           right_x = tmp_x;
01102           right1  = prev;
01103           right2  = point;
01104         }
01105       }
01106 
01107       if ( left1 && right1 )
01108       {
01109         if ( left1->y < left2->y && right1->y > right2->y )
01110           result[i] = FT_ORIENTATION_TRUETYPE;
01111         else if ( left1->y > left2->y && right1->y < right2->y )
01112           result[i] = FT_ORIENTATION_POSTSCRIPT;
01113         else
01114           result[i] = FT_ORIENTATION_NONE;
01115       }
01116     }
01117 
01118     if ( result[0] != FT_ORIENTATION_NONE                     &&
01119          ( result[0] == result[1] || result[0] == result[2] ) )
01120       return result[0];
01121 
01122     if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )
01123       return result[1];
01124 
01125     return FT_ORIENTATION_TRUETYPE;
01126   }
01127 
01128 
01129 /* END */

Generated on Sun May 27 2012 04:33:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.