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

afloader.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  afloader.c                                                             */
00004 /*                                                                         */
00005 /*    Auto-fitter glyph loading routines (body).                           */
00006 /*                                                                         */
00007 /*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 #include "afloader.h"
00020 #include "afhints.h"
00021 #include "afglobal.h"
00022 #include "aferrors.h"
00023 
00024 
00025   FT_LOCAL_DEF( FT_Error )
00026   af_loader_init( AF_Loader  loader,
00027                   FT_Memory  memory )
00028   {
00029     FT_ZERO( loader );
00030 
00031     af_glyph_hints_init( &loader->hints, memory );
00032 #ifdef AF_DEBUG
00033     _af_debug_hints = &loader->hints;
00034 #endif
00035     return FT_GlyphLoader_New( memory, &loader->gloader );
00036   }
00037 
00038 
00039   FT_LOCAL_DEF( FT_Error )
00040   af_loader_reset( AF_Loader  loader,
00041                    FT_Face    face )
00042   {
00043     FT_Error  error = AF_Err_Ok;
00044 
00045 
00046     loader->face    = face;
00047     loader->globals = (AF_FaceGlobals)face->autohint.data;
00048 
00049     FT_GlyphLoader_Rewind( loader->gloader );
00050 
00051     if ( loader->globals == NULL )
00052     {
00053       error = af_face_globals_new( face, &loader->globals );
00054       if ( !error )
00055       {
00056         face->autohint.data =
00057           (FT_Pointer)loader->globals;
00058         face->autohint.finalizer =
00059           (FT_Generic_Finalizer)af_face_globals_free;
00060       }
00061     }
00062 
00063     return error;
00064   }
00065 
00066 
00067   FT_LOCAL_DEF( void )
00068   af_loader_done( AF_Loader  loader )
00069   {
00070     af_glyph_hints_done( &loader->hints );
00071 
00072     loader->face    = NULL;
00073     loader->globals = NULL;
00074 
00075 #ifdef AF_DEBUG
00076     _af_debug_hints = NULL;
00077 #endif
00078     FT_GlyphLoader_Done( loader->gloader );
00079     loader->gloader = NULL;
00080   }
00081 
00082 
00083   static FT_Error
00084   af_loader_load_g( AF_Loader  loader,
00085                     AF_Scaler  scaler,
00086                     FT_UInt    glyph_index,
00087                     FT_Int32   load_flags,
00088                     FT_UInt    depth )
00089   {
00090     FT_Error          error;
00091     FT_Face           face     = loader->face;
00092     FT_GlyphLoader    gloader  = loader->gloader;
00093     AF_ScriptMetrics  metrics  = loader->metrics;
00094     AF_GlyphHints     hints    = &loader->hints;
00095     FT_GlyphSlot      slot     = face->glyph;
00096     FT_Slot_Internal  internal = slot->internal;
00097 
00098 
00099     error = FT_Load_Glyph( face, glyph_index, load_flags );
00100     if ( error )
00101       goto Exit;
00102 
00103     loader->transformed = internal->glyph_transformed;
00104     if ( loader->transformed )
00105     {
00106       FT_Matrix  inverse;
00107 
00108 
00109       loader->trans_matrix = internal->glyph_matrix;
00110       loader->trans_delta  = internal->glyph_delta;
00111 
00112       inverse = loader->trans_matrix;
00113       FT_Matrix_Invert( &inverse );
00114       FT_Vector_Transform( &loader->trans_delta, &inverse );
00115     }
00116 
00117     /* set linear metrics */
00118     slot->linearHoriAdvance = slot->metrics.horiAdvance;
00119     slot->linearVertAdvance = slot->metrics.vertAdvance;
00120 
00121     switch ( slot->format )
00122     {
00123     case FT_GLYPH_FORMAT_OUTLINE:
00124       /* translate the loaded glyph when an internal transform is needed */
00125       if ( loader->transformed )
00126         FT_Outline_Translate( &slot->outline,
00127                               loader->trans_delta.x,
00128                               loader->trans_delta.y );
00129 
00130       /* copy the outline points in the loader's current               */
00131       /* extra points which is used to keep original glyph coordinates */
00132       error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
00133                                            slot->outline.n_points + 4,
00134                                            slot->outline.n_contours );
00135       if ( error )
00136         goto Exit;
00137 
00138       FT_ARRAY_COPY( gloader->current.outline.points,
00139                      slot->outline.points,
00140                      slot->outline.n_points );
00141 
00142       FT_ARRAY_COPY( gloader->current.outline.contours,
00143                      slot->outline.contours,
00144                      slot->outline.n_contours );
00145 
00146       FT_ARRAY_COPY( gloader->current.outline.tags,
00147                      slot->outline.tags,
00148                      slot->outline.n_points );
00149 
00150       gloader->current.outline.n_points   = slot->outline.n_points;
00151       gloader->current.outline.n_contours = slot->outline.n_contours;
00152 
00153       /* compute original horizontal phantom points (and ignore */
00154       /* vertical ones)                                         */
00155       loader->pp1.x = hints->x_delta;
00156       loader->pp1.y = hints->y_delta;
00157       loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
00158                                  hints->x_scale ) + hints->x_delta;
00159       loader->pp2.y = hints->y_delta;
00160 
00161       /* be sure to check for spacing glyphs */
00162       if ( slot->outline.n_points == 0 )
00163         goto Hint_Metrics;
00164 
00165       /* now load the slot image into the auto-outline and run the */
00166       /* automatic hinting process                                 */
00167       if ( metrics->clazz->script_hints_apply )
00168         metrics->clazz->script_hints_apply( hints,
00169                                             &gloader->current.outline,
00170                                             metrics );
00171 
00172       /* we now need to hint the metrics according to the change in */
00173       /* width/positioning that occurred during the hinting process */
00174       if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
00175       {
00176         FT_Pos        old_rsb, old_lsb, new_lsb;
00177         FT_Pos        pp1x_uh, pp2x_uh;
00178         AF_AxisHints  axis  = &hints->axis[AF_DIMENSION_HORZ];
00179         AF_Edge       edge1 = axis->edges;         /* leftmost edge  */
00180         AF_Edge       edge2 = edge1 +
00181                               axis->num_edges - 1; /* rightmost edge */
00182 
00183 
00184         if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
00185         {
00186           old_rsb = loader->pp2.x - edge2->opos;
00187           old_lsb = edge1->opos;
00188           new_lsb = edge1->pos;
00189 
00190           /* remember unhinted values to later account */
00191           /* for rounding errors                       */
00192 
00193           pp1x_uh = new_lsb    - old_lsb;
00194           pp2x_uh = edge2->pos + old_rsb;
00195 
00196           /* prefer too much space over too little space */
00197           /* for very small sizes                        */
00198 
00199           if ( old_lsb < 24 )
00200             pp1x_uh -= 8;
00201 
00202           if ( old_rsb < 24 )
00203             pp2x_uh += 8;
00204 
00205           loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
00206           loader->pp2.x = FT_PIX_ROUND( pp2x_uh );
00207 
00208           if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
00209             loader->pp1.x -= 64;
00210 
00211           if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
00212             loader->pp2.x += 64;
00213 
00214           slot->lsb_delta = loader->pp1.x - pp1x_uh;
00215           slot->rsb_delta = loader->pp2.x - pp2x_uh;
00216         }
00217         else
00218         {
00219           FT_Pos  pp1x = loader->pp1.x;
00220           FT_Pos  pp2x = loader->pp2.x;
00221 
00222 
00223           loader->pp1.x = FT_PIX_ROUND( pp1x );
00224           loader->pp2.x = FT_PIX_ROUND( pp2x );
00225 
00226           slot->lsb_delta = loader->pp1.x - pp1x;
00227           slot->rsb_delta = loader->pp2.x - pp2x;
00228         }
00229       }
00230       else
00231       {
00232         FT_Pos  pp1x = loader->pp1.x;
00233         FT_Pos  pp2x = loader->pp2.x;
00234 
00235 
00236         loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
00237         loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
00238 
00239         slot->lsb_delta = loader->pp1.x - pp1x;
00240         slot->rsb_delta = loader->pp2.x - pp2x;
00241       }
00242 
00243       /* good, we simply add the glyph to our loader's base */
00244       FT_GlyphLoader_Add( gloader );
00245       break;
00246 
00247     case FT_GLYPH_FORMAT_COMPOSITE:
00248       {
00249         FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
00250         FT_UInt      num_base_subgs, start_point;
00251         FT_SubGlyph  subglyph;
00252 
00253 
00254         start_point = gloader->base.outline.n_points;
00255 
00256         /* first of all, copy the subglyph descriptors in the glyph loader */
00257         error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
00258         if ( error )
00259           goto Exit;
00260 
00261         FT_ARRAY_COPY( gloader->current.subglyphs,
00262                        slot->subglyphs,
00263                        num_subglyphs );
00264 
00265         gloader->current.num_subglyphs = num_subglyphs;
00266         num_base_subgs                 = gloader->base.num_subglyphs;
00267 
00268         /* now, read each subglyph independently */
00269         for ( nn = 0; nn < num_subglyphs; nn++ )
00270         {
00271           FT_Vector  pp1, pp2;
00272           FT_Pos     x, y;
00273           FT_UInt    num_points, num_new_points, num_base_points;
00274 
00275 
00276           /* gloader.current.subglyphs can change during glyph loading due */
00277           /* to re-allocation -- we must recompute the current subglyph on */
00278           /* each iteration                                                */
00279           subglyph = gloader->base.subglyphs + num_base_subgs + nn;
00280 
00281           pp1 = loader->pp1;
00282           pp2 = loader->pp2;
00283 
00284           num_base_points = gloader->base.outline.n_points;
00285 
00286           error = af_loader_load_g( loader, scaler, subglyph->index,
00287                                     load_flags, depth + 1 );
00288           if ( error )
00289             goto Exit;
00290 
00291           /* recompute subglyph pointer */
00292           subglyph = gloader->base.subglyphs + num_base_subgs + nn;
00293 
00294           if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
00295           {
00296             pp1 = loader->pp1;
00297             pp2 = loader->pp2;
00298           }
00299           else
00300           {
00301             loader->pp1 = pp1;
00302             loader->pp2 = pp2;
00303           }
00304 
00305           num_points     = gloader->base.outline.n_points;
00306           num_new_points = num_points - num_base_points;
00307 
00308           /* now perform the transform required for this subglyph */
00309 
00310           if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
00311                                    FT_SUBGLYPH_FLAG_XY_SCALE |
00312                                    FT_SUBGLYPH_FLAG_2X2      ) )
00313           {
00314             FT_Vector*  cur   = gloader->base.outline.points +
00315                                 num_base_points;
00316             FT_Vector*  limit = cur + num_new_points;
00317 
00318 
00319             for ( ; cur < limit; cur++ )
00320               FT_Vector_Transform( cur, &subglyph->transform );
00321           }
00322 
00323           /* apply offset */
00324 
00325           if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
00326           {
00327             FT_Int      k = subglyph->arg1;
00328             FT_UInt     l = subglyph->arg2;
00329             FT_Vector*  p1;
00330             FT_Vector*  p2;
00331 
00332 
00333             if ( start_point + k >= num_base_points         ||
00334                                l >= (FT_UInt)num_new_points )
00335             {
00336               error = AF_Err_Invalid_Composite;
00337               goto Exit;
00338             }
00339 
00340             l += num_base_points;
00341 
00342             /* for now, only use the current point coordinates;    */
00343             /* we may consider another approach in the near future */
00344             p1 = gloader->base.outline.points + start_point + k;
00345             p2 = gloader->base.outline.points + start_point + l;
00346 
00347             x = p1->x - p2->x;
00348             y = p1->y - p2->y;
00349           }
00350           else
00351           {
00352             x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
00353             y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
00354 
00355             x = FT_PIX_ROUND( x );
00356             y = FT_PIX_ROUND( y );
00357           }
00358 
00359           {
00360             FT_Outline  dummy = gloader->base.outline;
00361 
00362 
00363             dummy.points  += num_base_points;
00364             dummy.n_points = (short)num_new_points;
00365 
00366             FT_Outline_Translate( &dummy, x, y );
00367           }
00368         }
00369       }
00370       break;
00371 
00372     default:
00373       /* we don't support other formats (yet?) */
00374       error = AF_Err_Unimplemented_Feature;
00375     }
00376 
00377   Hint_Metrics:
00378     if ( depth == 0 )
00379     {
00380       FT_BBox    bbox;
00381       FT_Vector  vvector;
00382 
00383 
00384       vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
00385       vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
00386       vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
00387       vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );
00388 
00389       /* transform the hinted outline if needed */
00390       if ( loader->transformed )
00391       {
00392         FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
00393         FT_Vector_Transform( &vvector, &loader->trans_matrix );
00394       }
00395 #if 1
00396       /* we must translate our final outline by -pp1.x and compute */
00397       /* the new metrics                                           */
00398       if ( loader->pp1.x )
00399         FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
00400 #endif
00401       FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
00402 
00403       bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
00404       bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
00405       bbox.xMax = FT_PIX_CEIL(  bbox.xMax );
00406       bbox.yMax = FT_PIX_CEIL(  bbox.yMax );
00407 
00408       slot->metrics.width        = bbox.xMax - bbox.xMin;
00409       slot->metrics.height       = bbox.yMax - bbox.yMin;
00410       slot->metrics.horiBearingX = bbox.xMin;
00411       slot->metrics.horiBearingY = bbox.yMax;
00412 
00413       slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
00414       slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
00415 
00416       /* for mono-width fonts (like Andale, Courier, etc.) we need */
00417       /* to keep the original rounded advance width; ditto for     */
00418       /* digits if all have the same advance width                 */
00419 #if 0
00420       if ( !FT_IS_FIXED_WIDTH( slot->face ) )
00421         slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
00422       else
00423         slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
00424                                                x_scale );
00425 #else
00426       if ( FT_IS_FIXED_WIDTH( slot->face )                              ||
00427            ( af_face_globals_is_digit( loader->globals, glyph_index ) &&
00428              metrics->digits_have_same_width                          ) )
00429       {
00430         slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
00431                                                metrics->scaler.x_scale );
00432 
00433         /* Set delta values to 0.  Otherwise code that uses them is */
00434         /* going to ruin the fixed advance width.                   */
00435         slot->lsb_delta = 0;
00436         slot->rsb_delta = 0;
00437       }
00438       else
00439       {
00440         /* non-spacing glyphs must stay as-is */
00441         if ( slot->metrics.horiAdvance )
00442           slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
00443       }
00444 #endif
00445 
00446       slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
00447                                               metrics->scaler.y_scale );
00448 
00449       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
00450       slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
00451 
00452       /* now copy outline into glyph slot */
00453       FT_GlyphLoader_Rewind( internal->loader );
00454       error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
00455       if ( error )
00456         goto Exit;
00457 
00458       slot->outline = internal->loader->base.outline;
00459       slot->format  = FT_GLYPH_FORMAT_OUTLINE;
00460     }
00461 
00462 #ifdef DEBUG_HINTER
00463     af_debug_hinter = hinter;
00464 #endif
00465 
00466   Exit:
00467     return error;
00468   }
00469 
00470 
00471   FT_LOCAL_DEF( FT_Error )
00472   af_loader_load_glyph( AF_Loader  loader,
00473                         FT_Face    face,
00474                         FT_UInt    gindex,
00475                         FT_UInt32  load_flags )
00476   {
00477     FT_Error      error;
00478     FT_Size       size = face->size;
00479     AF_ScalerRec  scaler;
00480 
00481 
00482     if ( !size )
00483       return AF_Err_Invalid_Argument;
00484 
00485     FT_ZERO( &scaler );
00486 
00487     scaler.face    = face;
00488     scaler.x_scale = size->metrics.x_scale;
00489     scaler.x_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
00490     scaler.y_scale = size->metrics.y_scale;
00491     scaler.y_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
00492 
00493     scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
00494     scaler.flags       = 0;  /* XXX: fix this */
00495 
00496     error = af_loader_reset( loader, face );
00497     if ( !error )
00498     {
00499       AF_ScriptMetrics  metrics;
00500       FT_UInt           options = 0;
00501 
00502 
00503 #ifdef FT_OPTION_AUTOFIT2
00504       /* XXX: undocumented hook to activate the latin2 hinter */
00505       if ( load_flags & ( 1UL << 20 ) )
00506         options = 2;
00507 #endif
00508 
00509       error = af_face_globals_get_metrics( loader->globals, gindex,
00510                                            options, &metrics );
00511       if ( !error )
00512       {
00513         loader->metrics = metrics;
00514 
00515         if ( metrics->clazz->script_metrics_scale )
00516           metrics->clazz->script_metrics_scale( metrics, &scaler );
00517         else
00518           metrics->scaler = scaler;
00519 
00520         load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
00521         load_flags &= ~FT_LOAD_RENDER;
00522 
00523         if ( metrics->clazz->script_hints_init )
00524         {
00525           error = metrics->clazz->script_hints_init( &loader->hints,
00526                                                      metrics );
00527           if ( error )
00528             goto Exit;
00529         }
00530 
00531         error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
00532       }
00533     }
00534   Exit:
00535     return error;
00536   }
00537 
00538 
00539 /* END */

Generated on Sat May 26 2012 04:32:29 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.