t1cmap.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /***************************************************************************/
  2. /* */
  3. /* t1cmap.c */
  4. /* */
  5. /* Type 1 character map support (body). */
  6. /* */
  7. /* Copyright 2002 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 "t1cmap.h"
  18. #include FT_INTERNAL_DEBUG_H
  19. /*************************************************************************/
  20. /*************************************************************************/
  21. /***** *****/
  22. /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
  23. /***** *****/
  24. /*************************************************************************/
  25. /*************************************************************************/
  26. static void
  27. t1_cmap_std_init( T1_CMapStd cmap,
  28. FT_Int is_expert )
  29. {
  30. T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
  31. PSNames_Service psnames = (PSNames_Service)face->psnames;
  32. cmap->num_glyphs = face->type1.num_glyphs;
  33. cmap->glyph_names = (const char* const*)face->type1.glyph_names;
  34. cmap->sid_to_string = psnames->adobe_std_strings;
  35. cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding
  36. : psnames->adobe_std_encoding;
  37. FT_ASSERT( cmap->code_to_sid != NULL );
  38. }
  39. FT_CALLBACK_DEF( void )
  40. t1_cmap_std_done( T1_CMapStd cmap )
  41. {
  42. cmap->num_glyphs = 0;
  43. cmap->glyph_names = NULL;
  44. cmap->sid_to_string = NULL;
  45. cmap->code_to_sid = NULL;
  46. }
  47. FT_CALLBACK_DEF( FT_UInt )
  48. t1_cmap_std_char_index( T1_CMapStd cmap,
  49. FT_UInt32 char_code )
  50. {
  51. FT_UInt result = 0;
  52. if ( char_code < 256 )
  53. {
  54. FT_UInt code, n;
  55. const char* glyph_name;
  56. /* convert character code to Adobe SID string */
  57. code = cmap->code_to_sid[char_code];
  58. glyph_name = cmap->sid_to_string( code );
  59. /* look for the corresponding glyph name */
  60. for ( n = 0; n < cmap->num_glyphs; n++ )
  61. {
  62. const char* gname = cmap->glyph_names[n];
  63. if ( gname && gname[0] == glyph_name[0] &&
  64. ft_strcmp( gname, glyph_name ) == 0 )
  65. {
  66. result = n;
  67. break;
  68. }
  69. }
  70. }
  71. return result;
  72. }
  73. FT_CALLBACK_DEF( FT_UInt )
  74. t1_cmap_std_char_next( T1_CMapStd cmap,
  75. FT_UInt32 *pchar_code )
  76. {
  77. FT_UInt result = 0;
  78. FT_UInt32 char_code = *pchar_code + 1;
  79. while ( char_code < 256 )
  80. {
  81. result = t1_cmap_std_char_index( cmap, char_code );
  82. if ( result != 0 )
  83. goto Exit;
  84. char_code++;
  85. }
  86. char_code = 0;
  87. Exit:
  88. *pchar_code = char_code;
  89. return result;
  90. }
  91. FT_CALLBACK_DEF( FT_Error )
  92. t1_cmap_standard_init( T1_CMapStd cmap )
  93. {
  94. t1_cmap_std_init( cmap, 0 );
  95. return 0;
  96. }
  97. FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
  98. t1_cmap_standard_class_rec =
  99. {
  100. sizeof ( T1_CMapStdRec ),
  101. (FT_CMap_InitFunc) t1_cmap_standard_init,
  102. (FT_CMap_DoneFunc) t1_cmap_std_done,
  103. (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
  104. (FT_CMap_CharNextFunc) t1_cmap_std_char_next
  105. };
  106. FT_CALLBACK_DEF( FT_Error )
  107. t1_cmap_expert_init( T1_CMapStd cmap )
  108. {
  109. t1_cmap_std_init( cmap, 1 );
  110. return 0;
  111. }
  112. FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
  113. t1_cmap_expert_class_rec =
  114. {
  115. sizeof ( T1_CMapStdRec ),
  116. (FT_CMap_InitFunc) t1_cmap_expert_init,
  117. (FT_CMap_DoneFunc) t1_cmap_std_done,
  118. (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
  119. (FT_CMap_CharNextFunc) t1_cmap_std_char_next
  120. };
  121. /*************************************************************************/
  122. /*************************************************************************/
  123. /***** *****/
  124. /***** TYPE1 CUSTOM ENCODING CMAP *****/
  125. /***** *****/
  126. /*************************************************************************/
  127. /*************************************************************************/
  128. FT_CALLBACK_DEF( FT_Error )
  129. t1_cmap_custom_init( T1_CMapCustom cmap )
  130. {
  131. T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
  132. T1_Encoding encoding = &face->type1.encoding;
  133. cmap->first = encoding->code_first;
  134. cmap->count = (FT_UInt)( encoding->code_last - cmap->first + 1 );
  135. cmap->indices = encoding->char_index;
  136. FT_ASSERT( cmap->indices != NULL );
  137. FT_ASSERT( encoding->code_first <= encoding->code_last );
  138. return 0;
  139. }
  140. FT_CALLBACK_DEF( void )
  141. t1_cmap_custom_done( T1_CMapCustom cmap )
  142. {
  143. cmap->indices = NULL;
  144. cmap->first = 0;
  145. cmap->count = 0;
  146. }
  147. FT_CALLBACK_DEF( FT_UInt )
  148. t1_cmap_custom_char_index( T1_CMapCustom cmap,
  149. FT_UInt32 char_code )
  150. {
  151. FT_UInt result = 0;
  152. if ( ( char_code >= cmap->first ) &&
  153. ( char_code < ( cmap->first + cmap->count ) ) )
  154. result = cmap->indices[char_code];
  155. return result;
  156. }
  157. FT_CALLBACK_DEF( FT_UInt )
  158. t1_cmap_custom_char_next( T1_CMapCustom cmap,
  159. FT_UInt32 *pchar_code )
  160. {
  161. FT_UInt result = 0;
  162. FT_UInt32 char_code = *pchar_code;
  163. ++char_code;
  164. if ( char_code < cmap->first )
  165. char_code = cmap->first;
  166. for ( ; char_code < ( cmap->first + cmap->count ); char_code++ )
  167. {
  168. result = cmap->indices[char_code];
  169. if ( result != 0 )
  170. goto Exit;
  171. }
  172. char_code = 0;
  173. Exit:
  174. *pchar_code = char_code;
  175. return result;
  176. }
  177. FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
  178. t1_cmap_custom_class_rec =
  179. {
  180. sizeof ( T1_CMapCustomRec ),
  181. (FT_CMap_InitFunc) t1_cmap_custom_init,
  182. (FT_CMap_DoneFunc) t1_cmap_custom_done,
  183. (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,
  184. (FT_CMap_CharNextFunc) t1_cmap_custom_char_next
  185. };
  186. /*************************************************************************/
  187. /*************************************************************************/
  188. /***** *****/
  189. /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/
  190. /***** *****/
  191. /*************************************************************************/
  192. /*************************************************************************/
  193. FT_CALLBACK_DEF( FT_Int )
  194. t1_cmap_uni_pair_compare( const void* pair1,
  195. const void* pair2 )
  196. {
  197. FT_UInt32 u1 = ((T1_CMapUniPair)pair1)->unicode;
  198. FT_UInt32 u2 = ((T1_CMapUniPair)pair2)->unicode;
  199. if ( u1 < u2 )
  200. return -1;
  201. if ( u1 > u2 )
  202. return +1;
  203. return 0;
  204. }
  205. FT_CALLBACK_DEF( FT_Error )
  206. t1_cmap_unicode_init( T1_CMapUnicode cmap )
  207. {
  208. FT_Error error;
  209. FT_UInt count;
  210. T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
  211. FT_Memory memory = FT_FACE_MEMORY( face );
  212. PSNames_Service psnames = (PSNames_Service)face->psnames;
  213. cmap->num_pairs = 0;
  214. cmap->pairs = NULL;
  215. count = face->type1.num_glyphs;
  216. if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
  217. {
  218. FT_UInt n, new_count;
  219. T1_CMapUniPair pair;
  220. FT_UInt32 uni_code;
  221. pair = cmap->pairs;
  222. for ( n = 0; n < count; n++ )
  223. {
  224. const char* gname = face->type1.glyph_names[n];
  225. /* build unsorted pair table by matching glyph names */
  226. if ( gname )
  227. {
  228. uni_code = psnames->unicode_value( gname );
  229. if ( uni_code != 0 )
  230. {
  231. pair->unicode = uni_code;
  232. pair->gindex = n;
  233. pair++;
  234. }
  235. }
  236. }
  237. new_count = (FT_UInt)( pair - cmap->pairs );
  238. if ( new_count == 0 )
  239. {
  240. /* there are no unicode characters in here! */
  241. FT_FREE( cmap->pairs );
  242. error = FT_Err_Invalid_Argument;
  243. }
  244. else
  245. {
  246. /* re-allocate if the new array is much smaller than the original */
  247. /* one */
  248. if ( new_count != count && new_count < count / 2 )
  249. {
  250. (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
  251. error = 0;
  252. }
  253. /* sort the pairs table to allow efficient binary searches */
  254. ft_qsort( cmap->pairs,
  255. new_count,
  256. sizeof ( T1_CMapUniPairRec ),
  257. t1_cmap_uni_pair_compare );
  258. cmap->num_pairs = new_count;
  259. }
  260. }
  261. return error;
  262. }
  263. FT_CALLBACK_DEF( void )
  264. t1_cmap_unicode_done( T1_CMapUnicode cmap )
  265. {
  266. FT_Face face = FT_CMAP_FACE(cmap);
  267. FT_Memory memory = FT_FACE_MEMORY(face);
  268. FT_FREE( cmap->pairs );
  269. cmap->num_pairs = 0;
  270. }
  271. FT_CALLBACK_DEF( FT_UInt )
  272. t1_cmap_unicode_char_index( T1_CMapUnicode cmap,
  273. FT_UInt32 char_code )
  274. {
  275. FT_UInt min = 0;
  276. FT_UInt max = cmap->num_pairs;
  277. FT_UInt mid;
  278. T1_CMapUniPair pair;
  279. while ( min < max )
  280. {
  281. mid = min + ( max - min ) / 2;
  282. pair = cmap->pairs + mid;
  283. if ( pair->unicode == char_code )
  284. return pair->gindex;
  285. if ( pair->unicode < char_code )
  286. min = mid + 1;
  287. else
  288. max = mid;
  289. }
  290. return 0;
  291. }
  292. FT_CALLBACK_DEF( FT_UInt )
  293. t1_cmap_unicode_char_next( T1_CMapUnicode cmap,
  294. FT_UInt32 *pchar_code )
  295. {
  296. FT_UInt result = 0;
  297. FT_UInt32 char_code = *pchar_code + 1;
  298. Restart:
  299. {
  300. FT_UInt min = 0;
  301. FT_UInt max = cmap->num_pairs;
  302. FT_UInt mid;
  303. T1_CMapUniPair pair;
  304. while ( min < max )
  305. {
  306. mid = min + ( ( max - min ) >> 1 );
  307. pair = cmap->pairs + mid;
  308. if ( pair->unicode == char_code )
  309. {
  310. result = pair->gindex;
  311. if ( result != 0 )
  312. goto Exit;
  313. char_code++;
  314. goto Restart;
  315. }
  316. if ( pair->unicode < char_code )
  317. min = mid+1;
  318. else
  319. max = mid;
  320. }
  321. /* we didn't find it, but we have a pair just above it */
  322. char_code = 0;
  323. if ( min < cmap->num_pairs )
  324. {
  325. pair = cmap->pairs + min;
  326. result = pair->gindex;
  327. if ( result != 0 )
  328. char_code = pair->unicode;
  329. }
  330. }
  331. Exit:
  332. *pchar_code = char_code;
  333. return result;
  334. }
  335. FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
  336. t1_cmap_unicode_class_rec =
  337. {
  338. sizeof ( T1_CMapUnicodeRec ),
  339. (FT_CMap_InitFunc) t1_cmap_unicode_init,
  340. (FT_CMap_DoneFunc) t1_cmap_unicode_done,
  341. (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,
  342. (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next
  343. };
  344. /* END */