/src/compiler/android-ndk/jni/freetype/src/psnames/psmodule.c

http://ftk.googlecode.com/ · C · 595 lines · 405 code · 135 blank · 55 comment · 79 complexity · 0bb73bda3ac8b2fa0efce94b3417d877 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. FT_FREE( table->maps );
  300. if ( !error )
  301. error = PSnames_Err_Invalid_Argument; /* No unicode chars here! */
  302. }
  303. else {
  304. /* Reallocate if the number of used entries is much smaller. */
  305. if ( count < num_glyphs / 2 )
  306. {
  307. (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
  308. error = PSnames_Err_Ok;
  309. }
  310. /* Sort the table in increasing order of unicode values, */
  311. /* taking care of glyph variants. */
  312. ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
  313. compare_uni_maps );
  314. }
  315. table->num_maps = count;
  316. }
  317. return error;
  318. }
  319. static FT_UInt
  320. ps_unicodes_char_index( PS_Unicodes table,
  321. FT_UInt32 unicode )
  322. {
  323. PS_UniMap *min, *max, *mid, *result = NULL;
  324. /* Perform a binary search on the table. */
  325. min = table->maps;
  326. max = min + table->num_maps - 1;
  327. while ( min <= max )
  328. {
  329. FT_UInt32 base_glyph;
  330. mid = min + ( ( max - min ) >> 1 );
  331. if ( mid->unicode == unicode )
  332. {
  333. result = mid;
  334. break;
  335. }
  336. base_glyph = BASE_GLYPH( mid->unicode );
  337. if ( base_glyph == unicode )
  338. result = mid; /* remember match but continue search for base glyph */
  339. if ( min == max )
  340. break;
  341. if ( base_glyph < unicode )
  342. min = mid + 1;
  343. else
  344. max = mid - 1;
  345. }
  346. if ( result )
  347. return result->glyph_index;
  348. else
  349. return 0;
  350. }
  351. static FT_UInt32
  352. ps_unicodes_char_next( PS_Unicodes table,
  353. FT_UInt32 *unicode )
  354. {
  355. FT_UInt result = 0;
  356. FT_UInt32 char_code = *unicode + 1;
  357. {
  358. FT_UInt min = 0;
  359. FT_UInt max = table->num_maps;
  360. FT_UInt mid;
  361. PS_UniMap* map;
  362. FT_UInt32 base_glyph;
  363. while ( min < max )
  364. {
  365. mid = min + ( ( max - min ) >> 1 );
  366. map = table->maps + mid;
  367. if ( map->unicode == char_code )
  368. {
  369. result = map->glyph_index;
  370. goto Exit;
  371. }
  372. base_glyph = BASE_GLYPH( map->unicode );
  373. if ( base_glyph == char_code )
  374. result = map->glyph_index;
  375. if ( base_glyph < char_code )
  376. min = mid + 1;
  377. else
  378. max = mid;
  379. }
  380. if ( result )
  381. goto Exit; /* we have a variant glyph */
  382. /* we didn't find it; check whether we have a map just above it */
  383. char_code = 0;
  384. if ( min < table->num_maps )
  385. {
  386. map = table->maps + min;
  387. result = map->glyph_index;
  388. char_code = BASE_GLYPH( map->unicode );
  389. }
  390. }
  391. Exit:
  392. *unicode = char_code;
  393. return result;
  394. }
  395. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  396. static const char*
  397. ps_get_macintosh_name( FT_UInt name_index )
  398. {
  399. if ( name_index >= FT_NUM_MAC_NAMES )
  400. name_index = 0;
  401. return ft_standard_glyph_names + ft_mac_names[name_index];
  402. }
  403. static const char*
  404. ps_get_standard_strings( FT_UInt sid )
  405. {
  406. if ( sid >= FT_NUM_SID_NAMES )
  407. return 0;
  408. return ft_standard_glyph_names + ft_sid_names[sid];
  409. }
  410. #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
  411. FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
  412. (PS_Unicode_ValueFunc) ps_unicode_value,
  413. (PS_Unicodes_InitFunc) ps_unicodes_init,
  414. (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
  415. (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
  416. (PS_Macintosh_NameFunc) ps_get_macintosh_name,
  417. (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  418. t1_standard_encoding,
  419. t1_expert_encoding
  420. )
  421. #else
  422. FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
  423. 0,
  424. 0,
  425. 0,
  426. 0,
  427. (PS_Macintosh_NameFunc) ps_get_macintosh_name,
  428. (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  429. t1_standard_encoding,
  430. t1_expert_encoding
  431. )
  432. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  433. FT_DEFINE_SERVICEDESCREC1(pscmaps_services,
  434. FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
  435. )
  436. static FT_Pointer
  437. psnames_get_service( FT_Module module,
  438. const char* service_id )
  439. {
  440. FT_UNUSED( module );
  441. return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
  442. }
  443. #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
  444. #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  445. #define PUT_PS_NAMES_SERVICE(a) 0
  446. #else
  447. #define PUT_PS_NAMES_SERVICE(a) a
  448. #endif
  449. FT_DEFINE_MODULE(psnames_module_class,
  450. 0, /* this is not a font driver, nor a renderer */
  451. sizeof ( FT_ModuleRec ),
  452. "psnames", /* driver name */
  453. 0x10000L, /* driver version */
  454. 0x20000L, /* driver requires FreeType 2 or above */
  455. PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET), /* module specific interface */
  456. (FT_Module_Constructor)0,
  457. (FT_Module_Destructor) 0,
  458. (FT_Module_Requester) PUT_PS_NAMES_SERVICE(psnames_get_service)
  459. )
  460. /* END */