/modules/freetype2/src/psnames/psmodule.c

http://github.com/zpao/v8monkey · C · 597 lines · 406 code · 135 blank · 56 comment · 78 complexity · 3a751dccef925cefeb6928eb8fec299d MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* psmodule.c */
  4. /* */
  5. /* PSNames module implementation (body). */
  6. /* */
  7. /* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 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 <ft2build.h>
  18. #include FT_INTERNAL_OBJECTS_H
  19. #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  20. #include "psmodule.h"
  21. #include "pstables.h"
  22. #include "psnamerr.h"
  23. #include "pspic.h"
  24. #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  25. #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
  26. #define VARIANT_BIT 0x80000000UL
  27. #define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
  28. /* Return the Unicode value corresponding to a given glyph. Note that */
  29. /* we do deal with glyph variants by detecting a non-initial dot in */
  30. /* the name, as in `A.swash' or `e.final'; in this case, the */
  31. /* VARIANT_BIT is set in the return value. */
  32. /* */
  33. static FT_UInt32
  34. ps_unicode_value( const char* glyph_name )
  35. {
  36. /* If the name begins with `uni', then the glyph name may be a */
  37. /* hard-coded unicode character code. */
  38. if ( glyph_name[0] == 'u' &&
  39. glyph_name[1] == 'n' &&
  40. glyph_name[2] == 'i' )
  41. {
  42. /* determine whether the next four characters following are */
  43. /* hexadecimal. */
  44. /* XXX: Add code to deal with ligatures, i.e. glyph names like */
  45. /* `uniXXXXYYYYZZZZ'... */
  46. FT_Int count;
  47. FT_UInt32 value = 0;
  48. const char* p = glyph_name + 3;
  49. for ( count = 4; count > 0; count--, p++ )
  50. {
  51. char c = *p;
  52. unsigned int d;
  53. d = (unsigned char)c - '0';
  54. if ( d >= 10 )
  55. {
  56. d = (unsigned char)c - 'A';
  57. if ( d >= 6 )
  58. d = 16;
  59. else
  60. d += 10;
  61. }
  62. /* Exit if a non-uppercase hexadecimal character was found */
  63. /* -- this also catches character codes below `0' since such */
  64. /* negative numbers cast to `unsigned int' are far too big. */
  65. if ( d >= 16 )
  66. break;
  67. value = ( value << 4 ) + d;
  68. }
  69. /* there must be exactly four hex digits */
  70. if ( count == 0 )
  71. {
  72. if ( *p == '\0' )
  73. return value;
  74. if ( *p == '.' )
  75. return (FT_UInt32)( value | VARIANT_BIT );
  76. }
  77. }
  78. /* If the name begins with `u', followed by four to six uppercase */
  79. /* hexadecimal digits, it is a hard-coded unicode character code. */
  80. if ( glyph_name[0] == 'u' )
  81. {
  82. FT_Int count;
  83. FT_UInt32 value = 0;
  84. const char* p = glyph_name + 1;
  85. for ( count = 6; count > 0; count--, p++ )
  86. {
  87. char c = *p;
  88. unsigned int d;
  89. d = (unsigned char)c - '0';
  90. if ( d >= 10 )
  91. {
  92. d = (unsigned char)c - 'A';
  93. if ( d >= 6 )
  94. d = 16;
  95. else
  96. d += 10;
  97. }
  98. if ( d >= 16 )
  99. break;
  100. value = ( value << 4 ) + d;
  101. }
  102. if ( count <= 2 )
  103. {
  104. if ( *p == '\0' )
  105. return value;
  106. if ( *p == '.' )
  107. return (FT_UInt32)( value | VARIANT_BIT );
  108. }
  109. }
  110. /* Look for a non-initial dot in the glyph name in order to */
  111. /* find variants like `A.swash', `e.final', etc. */
  112. {
  113. const char* p = glyph_name;
  114. const char* dot = NULL;
  115. for ( ; *p; p++ )
  116. {
  117. if ( *p == '.' && p > glyph_name )
  118. {
  119. dot = p;
  120. break;
  121. }
  122. }
  123. /* now look up the glyph in the Adobe Glyph List */
  124. if ( !dot )
  125. return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
  126. else
  127. return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
  128. VARIANT_BIT );
  129. }
  130. }
  131. /* ft_qsort callback to sort the unicode map */
  132. FT_CALLBACK_DEF( int )
  133. compare_uni_maps( const void* a,
  134. const void* b )
  135. {
  136. PS_UniMap* map1 = (PS_UniMap*)a;
  137. PS_UniMap* map2 = (PS_UniMap*)b;
  138. FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
  139. FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
  140. /* sort base glyphs before glyph variants */
  141. if ( unicode1 == unicode2 )
  142. {
  143. if ( map1->unicode > map2->unicode )
  144. return 1;
  145. else if ( map1->unicode < map2->unicode )
  146. return -1;
  147. else
  148. return 0;
  149. }
  150. else
  151. {
  152. if ( unicode1 > unicode2 )
  153. return 1;
  154. else if ( unicode1 < unicode2 )
  155. return -1;
  156. else
  157. return 0;
  158. }
  159. }
  160. /* support for extra glyphs not handled (well) in AGL; */
  161. /* we add extra mappings for them if necessary */
  162. #define EXTRA_GLYPH_LIST_SIZE 10
  163. static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
  164. {
  165. /* WGL 4 */
  166. 0x0394,
  167. 0x03A9,
  168. 0x2215,
  169. 0x00AD,
  170. 0x02C9,
  171. 0x03BC,
  172. 0x2219,
  173. 0x00A0,
  174. /* Romanian */
  175. 0x021A,
  176. 0x021B
  177. };
  178. static const char ft_extra_glyph_names[] =
  179. {
  180. 'D','e','l','t','a',0,
  181. 'O','m','e','g','a',0,
  182. 'f','r','a','c','t','i','o','n',0,
  183. 'h','y','p','h','e','n',0,
  184. 'm','a','c','r','o','n',0,
  185. 'm','u',0,
  186. 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
  187. 's','p','a','c','e',0,
  188. 'T','c','o','m','m','a','a','c','c','e','n','t',0,
  189. 't','c','o','m','m','a','a','c','c','e','n','t',0
  190. };
  191. static const FT_Int
  192. ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
  193. {
  194. 0,
  195. 6,
  196. 12,
  197. 21,
  198. 28,
  199. 35,
  200. 38,
  201. 53,
  202. 59,
  203. 72
  204. };
  205. static void
  206. ps_check_extra_glyph_name( const char* gname,
  207. FT_UInt glyph,
  208. FT_UInt* extra_glyphs,
  209. FT_UInt *states )
  210. {
  211. FT_UInt n;
  212. for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  213. {
  214. if ( ft_strcmp( ft_extra_glyph_names +
  215. ft_extra_glyph_name_offsets[n], gname ) == 0 )
  216. {
  217. if ( states[n] == 0 )
  218. {
  219. /* mark this extra glyph as a candidate for the cmap */
  220. states[n] = 1;
  221. extra_glyphs[n] = glyph;
  222. }
  223. return;
  224. }
  225. }
  226. }
  227. static void
  228. ps_check_extra_glyph_unicode( FT_UInt32 uni_char,
  229. FT_UInt *states )
  230. {
  231. FT_UInt n;
  232. for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  233. {
  234. if ( uni_char == ft_extra_glyph_unicodes[n] )
  235. {
  236. /* disable this extra glyph from being added to the cmap */
  237. states[n] = 2;
  238. return;
  239. }
  240. }
  241. }
  242. /* Build a table that maps Unicode values to glyph indices. */
  243. static FT_Error
  244. ps_unicodes_init( FT_Memory memory,
  245. PS_Unicodes table,
  246. FT_UInt num_glyphs,
  247. PS_GetGlyphNameFunc get_glyph_name,
  248. PS_FreeGlyphNameFunc free_glyph_name,
  249. FT_Pointer glyph_data )
  250. {
  251. FT_Error error;
  252. FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  253. FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
  254. /* we first allocate the table */
  255. table->num_maps = 0;
  256. table->maps = 0;
  257. if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
  258. {
  259. FT_UInt n;
  260. FT_UInt count;
  261. PS_UniMap* map;
  262. FT_UInt32 uni_char;
  263. map = table->maps;
  264. for ( n = 0; n < num_glyphs; n++ )
  265. {
  266. const char* gname = get_glyph_name( glyph_data, n );
  267. if ( gname )
  268. {
  269. ps_check_extra_glyph_name( gname, n,
  270. extra_glyphs, extra_glyph_list_states );
  271. uni_char = ps_unicode_value( gname );
  272. if ( BASE_GLYPH( uni_char ) != 0 )
  273. {
  274. ps_check_extra_glyph_unicode( uni_char,
  275. extra_glyph_list_states );
  276. map->unicode = uni_char;
  277. map->glyph_index = n;
  278. map++;
  279. }
  280. if ( free_glyph_name )
  281. free_glyph_name( glyph_data, gname );
  282. }
  283. }
  284. for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  285. {
  286. if ( extra_glyph_list_states[n] == 1 )
  287. {
  288. /* This glyph name has an additional representation. */
  289. /* Add it to the cmap. */
  290. map->unicode = ft_extra_glyph_unicodes[n];
  291. map->glyph_index = extra_glyphs[n];
  292. map++;
  293. }
  294. }
  295. /* now compress the table a bit */
  296. count = (FT_UInt)( map - table->maps );
  297. if ( count == 0 )
  298. {
  299. /* No unicode chars here! */
  300. FT_FREE( table->maps );
  301. if ( !error )
  302. error = PSnames_Err_No_Unicode_Glyph_Name;
  303. }
  304. else
  305. {
  306. /* Reallocate if the number of used entries is much smaller. */
  307. if ( count < num_glyphs / 2 )
  308. {
  309. (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
  310. error = PSnames_Err_Ok;
  311. }
  312. /* Sort the table in increasing order of unicode values, */
  313. /* taking care of glyph variants. */
  314. ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
  315. compare_uni_maps );
  316. }
  317. table->num_maps = count;
  318. }
  319. return error;
  320. }
  321. static FT_UInt
  322. ps_unicodes_char_index( PS_Unicodes table,
  323. FT_UInt32 unicode )
  324. {
  325. PS_UniMap *min, *max, *mid, *result = NULL;
  326. /* Perform a binary search on the table. */
  327. min = table->maps;
  328. max = min + table->num_maps - 1;
  329. while ( min <= max )
  330. {
  331. FT_UInt32 base_glyph;
  332. mid = min + ( ( max - min ) >> 1 );
  333. if ( mid->unicode == unicode )
  334. {
  335. result = mid;
  336. break;
  337. }
  338. base_glyph = BASE_GLYPH( mid->unicode );
  339. if ( base_glyph == unicode )
  340. result = mid; /* remember match but continue search for base glyph */
  341. if ( min == max )
  342. break;
  343. if ( base_glyph < unicode )
  344. min = mid + 1;
  345. else
  346. max = mid - 1;
  347. }
  348. if ( result )
  349. return result->glyph_index;
  350. else
  351. return 0;
  352. }
  353. static FT_UInt32
  354. ps_unicodes_char_next( PS_Unicodes table,
  355. FT_UInt32 *unicode )
  356. {
  357. FT_UInt result = 0;
  358. FT_UInt32 char_code = *unicode + 1;
  359. {
  360. FT_UInt min = 0;
  361. FT_UInt max = table->num_maps;
  362. FT_UInt mid;
  363. PS_UniMap* map;
  364. FT_UInt32 base_glyph;
  365. while ( min < max )
  366. {
  367. mid = min + ( ( max - min ) >> 1 );
  368. map = table->maps + mid;
  369. if ( map->unicode == char_code )
  370. {
  371. result = map->glyph_index;
  372. goto Exit;
  373. }
  374. base_glyph = BASE_GLYPH( map->unicode );
  375. if ( base_glyph == char_code )
  376. result = map->glyph_index;
  377. if ( base_glyph < char_code )
  378. min = mid + 1;
  379. else
  380. max = mid;
  381. }
  382. if ( result )
  383. goto Exit; /* we have a variant glyph */
  384. /* we didn't find it; check whether we have a map just above it */
  385. char_code = 0;
  386. if ( min < table->num_maps )
  387. {
  388. map = table->maps + min;
  389. result = map->glyph_index;
  390. char_code = BASE_GLYPH( map->unicode );
  391. }
  392. }
  393. Exit:
  394. *unicode = char_code;
  395. return result;
  396. }
  397. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  398. static const char*
  399. ps_get_macintosh_name( FT_UInt name_index )
  400. {
  401. if ( name_index >= FT_NUM_MAC_NAMES )
  402. name_index = 0;
  403. return ft_standard_glyph_names + ft_mac_names[name_index];
  404. }
  405. static const char*
  406. ps_get_standard_strings( FT_UInt sid )
  407. {
  408. if ( sid >= FT_NUM_SID_NAMES )
  409. return 0;
  410. return ft_standard_glyph_names + ft_sid_names[sid];
  411. }
  412. #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
  413. FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
  414. (PS_Unicode_ValueFunc) ps_unicode_value,
  415. (PS_Unicodes_InitFunc) ps_unicodes_init,
  416. (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
  417. (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
  418. (PS_Macintosh_NameFunc) ps_get_macintosh_name,
  419. (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  420. t1_standard_encoding,
  421. t1_expert_encoding
  422. )
  423. #else
  424. FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
  425. 0,
  426. 0,
  427. 0,
  428. 0,
  429. (PS_Macintosh_NameFunc) ps_get_macintosh_name,
  430. (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  431. t1_standard_encoding,
  432. t1_expert_encoding
  433. )
  434. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  435. FT_DEFINE_SERVICEDESCREC1(pscmaps_services,
  436. FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
  437. )
  438. static FT_Pointer
  439. psnames_get_service( FT_Module module,
  440. const char* service_id )
  441. {
  442. FT_UNUSED( module );
  443. return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
  444. }
  445. #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
  446. #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  447. #define PUT_PS_NAMES_SERVICE(a) 0
  448. #else
  449. #define PUT_PS_NAMES_SERVICE(a) a
  450. #endif
  451. FT_DEFINE_MODULE(psnames_module_class,
  452. 0, /* this is not a font driver, nor a renderer */
  453. sizeof ( FT_ModuleRec ),
  454. "psnames", /* driver name */
  455. 0x10000L, /* driver version */
  456. 0x20000L, /* driver requires FreeType 2 or above */
  457. PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET), /* module specific interface */
  458. (FT_Module_Constructor)0,
  459. (FT_Module_Destructor) 0,
  460. (FT_Module_Requester) PUT_PS_NAMES_SERVICE(psnames_get_service)
  461. )
  462. /* END */