afglobal.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  afglobal.c                                                             */
00004 /*                                                                         */
00005 /*    Auto-fitter routines to compute global hinting values (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 "afglobal.h"
00020 #include "afdummy.h"
00021 #include "aflatin.h"
00022 #include "afcjk.h"
00023 #include "afindic.h"
00024 #include "afpic.h"
00025 
00026 #include "aferrors.h"
00027 
00028 #ifdef FT_OPTION_AUTOFIT2
00029 #include "aflatin2.h"
00030 #endif
00031 
00032 #ifndef FT_CONFIG_OPTION_PIC
00033 
00034 /* when updating this table, don't forget to update 
00035   AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
00036 
00037   /* populate this list when you add new scripts */
00038   static AF_ScriptClass const  af_script_classes[] =
00039   {
00040     &af_dummy_script_class,
00041 #ifdef FT_OPTION_AUTOFIT2
00042     &af_latin2_script_class,
00043 #endif
00044     &af_latin_script_class,
00045     &af_cjk_script_class,
00046     &af_indic_script_class, 
00047     NULL  /* do not remove */
00048   };
00049 
00050 #endif /* FT_CONFIG_OPTION_PIC */
00051 
00052   /* index of default script in `af_script_classes' */
00053 #define AF_SCRIPT_LIST_DEFAULT  2
00054   /* a bit mask indicating an uncovered glyph       */
00055 #define AF_SCRIPT_LIST_NONE     0x7F
00056   /* if this flag is set, we have an ASCII digit    */
00057 #define AF_DIGIT                0x80
00058 
00059 
00060   /*
00061    *  Note that glyph_scripts[] is used to map each glyph into
00062    *  an index into the `af_script_classes' array.
00063    *
00064    */
00065   typedef struct  AF_FaceGlobalsRec_
00066   {
00067     FT_Face           face;
00068     FT_Long           glyph_count;    /* same as face->num_glyphs */
00069     FT_Byte*          glyph_scripts;
00070 
00071     AF_ScriptMetrics  metrics[AF_SCRIPT_MAX];
00072 
00073   } AF_FaceGlobalsRec;
00074 
00075 
00076   /* Compute the script index of each glyph within a given face. */
00077 
00078   static FT_Error
00079   af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
00080   {
00081     FT_Error    error       = AF_Err_Ok;
00082     FT_Face     face        = globals->face;
00083     FT_CharMap  old_charmap = face->charmap;
00084     FT_Byte*    gscripts    = globals->glyph_scripts;
00085     FT_UInt     ss, i;
00086 
00087 
00088     /* the value 255 means `uncovered glyph' */
00089     FT_MEM_SET( globals->glyph_scripts,
00090                 AF_SCRIPT_LIST_NONE,
00091                 globals->glyph_count );
00092 
00093     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
00094     if ( error )
00095     {
00096      /*
00097       *  Ignore this error; we simply use the default script.
00098       *  XXX: Shouldn't we rather disable hinting?
00099       */
00100       error = AF_Err_Ok;
00101       goto Exit;
00102     }
00103 
00104     /* scan each script in a Unicode charmap */
00105     for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
00106     {
00107       AF_ScriptClass      clazz = AF_SCRIPT_CLASSES_GET[ss];
00108       AF_Script_UniRange  range;
00109 
00110 
00111       if ( clazz->script_uni_ranges == NULL )
00112         continue;
00113 
00114       /*
00115        *  Scan all unicode points in the range and set the corresponding
00116        *  glyph script index.
00117        */
00118       for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
00119       {
00120         FT_ULong  charcode = range->first;
00121         FT_UInt   gindex;
00122 
00123 
00124         gindex = FT_Get_Char_Index( face, charcode );
00125 
00126         if ( gindex != 0                             &&
00127              gindex < (FT_ULong)globals->glyph_count &&
00128              gscripts[gindex] == AF_SCRIPT_LIST_NONE )
00129         {
00130           gscripts[gindex] = (FT_Byte)ss;
00131         }
00132 
00133         for (;;)
00134         {
00135           charcode = FT_Get_Next_Char( face, charcode, &gindex );
00136 
00137           if ( gindex == 0 || charcode > range->last )
00138             break;
00139 
00140           if ( gindex < (FT_ULong)globals->glyph_count &&
00141                gscripts[gindex] == AF_SCRIPT_LIST_NONE )
00142           {
00143             gscripts[gindex] = (FT_Byte)ss;
00144           }
00145         }
00146       }
00147     }
00148 
00149     /* mark ASCII digits */
00150     for ( i = 0x30; i <= 0x39; i++ )
00151     {
00152       FT_UInt  gindex = FT_Get_Char_Index( face, i );
00153 
00154 
00155       if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
00156         gscripts[gindex] |= AF_DIGIT;
00157     }
00158 
00159   Exit:
00160     /*
00161      *  By default, all uncovered glyphs are set to the latin script.
00162      *  XXX: Shouldn't we disable hinting or do something similar?
00163      */
00164     {
00165       FT_Long  nn;
00166 
00167 
00168       for ( nn = 0; nn < globals->glyph_count; nn++ )
00169       {
00170         if ( gscripts[nn] == AF_SCRIPT_LIST_NONE )
00171           gscripts[nn] = AF_SCRIPT_LIST_DEFAULT;
00172       }
00173     }
00174 
00175     FT_Set_Charmap( face, old_charmap );
00176     return error;
00177   }
00178 
00179 
00180   FT_LOCAL_DEF( FT_Error )
00181   af_face_globals_new( FT_Face          face,
00182                        AF_FaceGlobals  *aglobals )
00183   {
00184     FT_Error        error;
00185     FT_Memory       memory;
00186     AF_FaceGlobals  globals;
00187 
00188 
00189     memory = face->memory;
00190 
00191     if ( !FT_ALLOC( globals, sizeof ( *globals ) +
00192                              face->num_glyphs * sizeof ( FT_Byte ) ) )
00193     {
00194       globals->face          = face;
00195       globals->glyph_count   = face->num_glyphs;
00196       globals->glyph_scripts = (FT_Byte*)( globals + 1 );
00197 
00198       error = af_face_globals_compute_script_coverage( globals );
00199       if ( error )
00200       {
00201         af_face_globals_free( globals );
00202         globals = NULL;
00203       }
00204     }
00205 
00206     *aglobals = globals;
00207     return error;
00208   }
00209 
00210 
00211   FT_LOCAL_DEF( void )
00212   af_face_globals_free( AF_FaceGlobals  globals )
00213   {
00214     if ( globals )
00215     {
00216       FT_Memory  memory = globals->face->memory;
00217       FT_UInt    nn;
00218 
00219 
00220       for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
00221       {
00222         if ( globals->metrics[nn] )
00223         {
00224           AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
00225 
00226 
00227           FT_ASSERT( globals->metrics[nn]->clazz == clazz );
00228 
00229           if ( clazz->script_metrics_done )
00230             clazz->script_metrics_done( globals->metrics[nn] );
00231 
00232           FT_FREE( globals->metrics[nn] );
00233         }
00234       }
00235 
00236       globals->glyph_count   = 0;
00237       globals->glyph_scripts = NULL;  /* no need to free this one! */
00238       globals->face          = NULL;
00239 
00240       FT_FREE( globals );
00241     }
00242   }
00243 
00244 
00245   FT_LOCAL_DEF( FT_Error )
00246   af_face_globals_get_metrics( AF_FaceGlobals     globals,
00247                                FT_UInt            gindex,
00248                                FT_UInt            options,
00249                                AF_ScriptMetrics  *ametrics )
00250   {
00251     AF_ScriptMetrics  metrics = NULL;
00252     FT_UInt           gidx;
00253     AF_ScriptClass    clazz;
00254     FT_UInt           script     = options & 15;
00255     const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
00256                                      sizeof ( AF_SCRIPT_CLASSES_GET[0] );
00257     FT_Error          error      = AF_Err_Ok;
00258 
00259 
00260     if ( gindex >= (FT_ULong)globals->glyph_count )
00261     {
00262       error = AF_Err_Invalid_Argument;
00263       goto Exit;
00264     }
00265 
00266     gidx = script;
00267     if ( gidx == 0 || gidx + 1 >= script_max )
00268       gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
00269 
00270     clazz = AF_SCRIPT_CLASSES_GET[gidx];
00271     if ( script == 0 )
00272       script = clazz->script;
00273 
00274     metrics = globals->metrics[clazz->script];
00275     if ( metrics == NULL )
00276     {
00277       /* create the global metrics object when needed */
00278       FT_Memory  memory = globals->face->memory;
00279 
00280 
00281       if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
00282         goto Exit;
00283 
00284       metrics->clazz = clazz;
00285 
00286       if ( clazz->script_metrics_init )
00287       {
00288         error = clazz->script_metrics_init( metrics, globals->face );
00289         if ( error )
00290         {
00291           if ( clazz->script_metrics_done )
00292             clazz->script_metrics_done( metrics );
00293 
00294           FT_FREE( metrics );
00295           goto Exit;
00296         }
00297       }
00298 
00299       globals->metrics[clazz->script] = metrics;
00300     }
00301 
00302   Exit:
00303     *ametrics = metrics;
00304 
00305     return error;
00306   }
00307 
00308 
00309   FT_LOCAL_DEF( FT_Bool )
00310   af_face_globals_is_digit( AF_FaceGlobals  globals,
00311                             FT_UInt         gindex )
00312   {
00313     if ( gindex < (FT_ULong)globals->glyph_count )
00314       return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
00315 
00316     return (FT_Bool)0;
00317   }
00318 
00319 
00320 /* END */

Generated on Tue Jul 5 14:13:41 2011 for ROOT_528-00b_version by  doxygen 1.5.1