/modules/freetype2/src/autofit/afglobal.c

http://github.com/zpao/v8monkey · C · 323 lines · 205 code · 73 blank · 45 comment · 42 complexity · a03cdd924b27ced3047fe017b7e5b9f5 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* afglobal.c */
  4. /* */
  5. /* Auto-fitter routines to compute global hinting values (body). */
  6. /* */
  7. /* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
  8. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  9. /* */
  10. /* This file is part of the FreeType project, and may only be used, */
  11. /* modified, and distributed under the terms of the FreeType project */
  12. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  13. /* this file you indicate that you have read the license and */
  14. /* understand and accept it fully. */
  15. /* */
  16. /***************************************************************************/
  17. #include "afglobal.h"
  18. #include "afdummy.h"
  19. #include "aflatin.h"
  20. #include "afcjk.h"
  21. #include "afindic.h"
  22. #include "afpic.h"
  23. #include "aferrors.h"
  24. #ifdef FT_OPTION_AUTOFIT2
  25. #include "aflatin2.h"
  26. #endif
  27. #ifndef FT_CONFIG_OPTION_PIC
  28. /* when updating this table, don't forget to update
  29. AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
  30. /* populate this list when you add new scripts */
  31. static AF_ScriptClass const af_script_classes[] =
  32. {
  33. &af_dummy_script_class,
  34. #ifdef FT_OPTION_AUTOFIT2
  35. &af_latin2_script_class,
  36. #endif
  37. &af_latin_script_class,
  38. &af_cjk_script_class,
  39. &af_indic_script_class,
  40. NULL /* do not remove */
  41. };
  42. #endif /* FT_CONFIG_OPTION_PIC */
  43. /* index of default script in `af_script_classes' */
  44. #define AF_SCRIPT_LIST_DEFAULT 2
  45. /* a bit mask indicating an uncovered glyph */
  46. #define AF_SCRIPT_LIST_NONE 0x7F
  47. /* if this flag is set, we have an ASCII digit */
  48. #define AF_DIGIT 0x80
  49. /*
  50. * Note that glyph_scripts[] is used to map each glyph into
  51. * an index into the `af_script_classes' array.
  52. *
  53. */
  54. typedef struct AF_FaceGlobalsRec_
  55. {
  56. FT_Face face;
  57. FT_Long glyph_count; /* same as face->num_glyphs */
  58. FT_Byte* glyph_scripts;
  59. AF_ScriptMetrics metrics[AF_SCRIPT_MAX];
  60. } AF_FaceGlobalsRec;
  61. /* Compute the script index of each glyph within a given face. */
  62. static FT_Error
  63. af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
  64. {
  65. FT_Error error = AF_Err_Ok;
  66. FT_Face face = globals->face;
  67. FT_CharMap old_charmap = face->charmap;
  68. FT_Byte* gscripts = globals->glyph_scripts;
  69. FT_UInt ss, i;
  70. /* the value 255 means `uncovered glyph' */
  71. FT_MEM_SET( globals->glyph_scripts,
  72. AF_SCRIPT_LIST_NONE,
  73. globals->glyph_count );
  74. error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
  75. if ( error )
  76. {
  77. /*
  78. * Ignore this error; we simply use the default script.
  79. * XXX: Shouldn't we rather disable hinting?
  80. */
  81. error = AF_Err_Ok;
  82. goto Exit;
  83. }
  84. /* scan each script in a Unicode charmap */
  85. for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
  86. {
  87. AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[ss];
  88. AF_Script_UniRange range;
  89. if ( clazz->script_uni_ranges == NULL )
  90. continue;
  91. /*
  92. * Scan all unicode points in the range and set the corresponding
  93. * glyph script index.
  94. */
  95. for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
  96. {
  97. FT_ULong charcode = range->first;
  98. FT_UInt gindex;
  99. gindex = FT_Get_Char_Index( face, charcode );
  100. if ( gindex != 0 &&
  101. gindex < (FT_ULong)globals->glyph_count &&
  102. gscripts[gindex] == AF_SCRIPT_LIST_NONE )
  103. {
  104. gscripts[gindex] = (FT_Byte)ss;
  105. }
  106. for (;;)
  107. {
  108. charcode = FT_Get_Next_Char( face, charcode, &gindex );
  109. if ( gindex == 0 || charcode > range->last )
  110. break;
  111. if ( gindex < (FT_ULong)globals->glyph_count &&
  112. gscripts[gindex] == AF_SCRIPT_LIST_NONE )
  113. {
  114. gscripts[gindex] = (FT_Byte)ss;
  115. }
  116. }
  117. }
  118. }
  119. /* mark ASCII digits */
  120. for ( i = 0x30; i <= 0x39; i++ )
  121. {
  122. FT_UInt gindex = FT_Get_Char_Index( face, i );
  123. if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
  124. gscripts[gindex] |= AF_DIGIT;
  125. }
  126. Exit:
  127. /*
  128. * By default, all uncovered glyphs are set to the latin script.
  129. * XXX: Shouldn't we disable hinting or do something similar?
  130. */
  131. {
  132. FT_Long nn;
  133. for ( nn = 0; nn < globals->glyph_count; nn++ )
  134. {
  135. if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_LIST_NONE )
  136. {
  137. gscripts[nn] &= ~AF_SCRIPT_LIST_NONE;
  138. gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT;
  139. }
  140. }
  141. }
  142. FT_Set_Charmap( face, old_charmap );
  143. return error;
  144. }
  145. FT_LOCAL_DEF( FT_Error )
  146. af_face_globals_new( FT_Face face,
  147. AF_FaceGlobals *aglobals )
  148. {
  149. FT_Error error;
  150. FT_Memory memory;
  151. AF_FaceGlobals globals = NULL;
  152. memory = face->memory;
  153. if ( !FT_ALLOC( globals, sizeof ( *globals ) +
  154. face->num_glyphs * sizeof ( FT_Byte ) ) )
  155. {
  156. globals->face = face;
  157. globals->glyph_count = face->num_glyphs;
  158. globals->glyph_scripts = (FT_Byte*)( globals + 1 );
  159. error = af_face_globals_compute_script_coverage( globals );
  160. if ( error )
  161. {
  162. af_face_globals_free( globals );
  163. globals = NULL;
  164. }
  165. }
  166. *aglobals = globals;
  167. return error;
  168. }
  169. FT_LOCAL_DEF( void )
  170. af_face_globals_free( AF_FaceGlobals globals )
  171. {
  172. if ( globals )
  173. {
  174. FT_Memory memory = globals->face->memory;
  175. FT_UInt nn;
  176. for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
  177. {
  178. if ( globals->metrics[nn] )
  179. {
  180. AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[nn];
  181. FT_ASSERT( globals->metrics[nn]->clazz == clazz );
  182. if ( clazz->script_metrics_done )
  183. clazz->script_metrics_done( globals->metrics[nn] );
  184. FT_FREE( globals->metrics[nn] );
  185. }
  186. }
  187. globals->glyph_count = 0;
  188. globals->glyph_scripts = NULL; /* no need to free this one! */
  189. globals->face = NULL;
  190. FT_FREE( globals );
  191. }
  192. }
  193. FT_LOCAL_DEF( FT_Error )
  194. af_face_globals_get_metrics( AF_FaceGlobals globals,
  195. FT_UInt gindex,
  196. FT_UInt options,
  197. AF_ScriptMetrics *ametrics )
  198. {
  199. AF_ScriptMetrics metrics = NULL;
  200. FT_UInt gidx;
  201. AF_ScriptClass clazz;
  202. FT_UInt script = options & 15;
  203. const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
  204. sizeof ( AF_SCRIPT_CLASSES_GET[0] );
  205. FT_Error error = AF_Err_Ok;
  206. if ( gindex >= (FT_ULong)globals->glyph_count )
  207. {
  208. error = AF_Err_Invalid_Argument;
  209. goto Exit;
  210. }
  211. gidx = script;
  212. if ( gidx == 0 || gidx + 1 >= script_max )
  213. gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
  214. clazz = AF_SCRIPT_CLASSES_GET[gidx];
  215. if ( script == 0 )
  216. script = clazz->script;
  217. metrics = globals->metrics[clazz->script];
  218. if ( metrics == NULL )
  219. {
  220. /* create the global metrics object when needed */
  221. FT_Memory memory = globals->face->memory;
  222. if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
  223. goto Exit;
  224. metrics->clazz = clazz;
  225. if ( clazz->script_metrics_init )
  226. {
  227. error = clazz->script_metrics_init( metrics, globals->face );
  228. if ( error )
  229. {
  230. if ( clazz->script_metrics_done )
  231. clazz->script_metrics_done( metrics );
  232. FT_FREE( metrics );
  233. goto Exit;
  234. }
  235. }
  236. globals->metrics[clazz->script] = metrics;
  237. }
  238. Exit:
  239. *ametrics = metrics;
  240. return error;
  241. }
  242. FT_LOCAL_DEF( FT_Bool )
  243. af_face_globals_is_digit( AF_FaceGlobals globals,
  244. FT_UInt gindex )
  245. {
  246. if ( gindex < (FT_ULong)globals->glyph_count )
  247. return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
  248. return (FT_Bool)0;
  249. }
  250. /* END */