ttcmap.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. /***************************************************************************/
  2. /* */
  3. /* ttcmap.c */
  4. /* */
  5. /* TrueType character mapping table (cmap) support (body). */
  6. /* */
  7. /* Copyright 1996-2001, 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 <ft2build.h>
  18. #include FT_INTERNAL_DEBUG_H
  19. #include "ttload.h"
  20. #include "ttcmap.h"
  21. #include "sferrors.h"
  22. /*************************************************************************/
  23. /* */
  24. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  25. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  26. /* messages during execution. */
  27. /* */
  28. #undef FT_COMPONENT
  29. #define FT_COMPONENT trace_ttcmap
  30. FT_CALLBACK_DEF( FT_UInt )
  31. code_to_index0( TT_CMapTable charmap,
  32. FT_ULong char_code );
  33. FT_CALLBACK_DEF( FT_ULong )
  34. code_to_next0( TT_CMapTable charmap,
  35. FT_ULong char_code );
  36. FT_CALLBACK_DEF( FT_UInt )
  37. code_to_index2( TT_CMapTable charmap,
  38. FT_ULong char_code );
  39. FT_CALLBACK_DEF( FT_ULong )
  40. code_to_next2( TT_CMapTable charmap,
  41. FT_ULong char_code );
  42. FT_CALLBACK_DEF( FT_UInt )
  43. code_to_index4( TT_CMapTable charmap,
  44. FT_ULong char_code );
  45. FT_CALLBACK_DEF( FT_ULong )
  46. code_to_next4( TT_CMapTable charmap,
  47. FT_ULong char_code );
  48. FT_CALLBACK_DEF( FT_UInt )
  49. code_to_index6( TT_CMapTable charmap,
  50. FT_ULong char_code );
  51. FT_CALLBACK_DEF( FT_ULong )
  52. code_to_next6( TT_CMapTable charmap,
  53. FT_ULong char_code );
  54. FT_CALLBACK_DEF( FT_UInt )
  55. code_to_index8_12( TT_CMapTable charmap,
  56. FT_ULong char_code );
  57. FT_CALLBACK_DEF( FT_ULong )
  58. code_to_next8_12( TT_CMapTable charmap,
  59. FT_ULong char_code );
  60. FT_CALLBACK_DEF( FT_UInt )
  61. code_to_index10( TT_CMapTable charmap,
  62. FT_ULong char_code );
  63. FT_CALLBACK_DEF( FT_ULong )
  64. code_to_next10( TT_CMapTable charmap,
  65. FT_ULong char_code );
  66. /*************************************************************************/
  67. /* */
  68. /* <Function> */
  69. /* tt_face_load_charmap */
  70. /* */
  71. /* <Description> */
  72. /* Loads a given TrueType character map into memory. */
  73. /* */
  74. /* <Input> */
  75. /* face :: A handle to the parent face object. */
  76. /* */
  77. /* stream :: A handle to the current stream object. */
  78. /* */
  79. /* <InOut> */
  80. /* table :: A pointer to a cmap object. */
  81. /* */
  82. /* <Return> */
  83. /* FreeType error code. 0 means success. */
  84. /* */
  85. /* <Note> */
  86. /* The function assumes that the stream is already in use (i.e., */
  87. /* opened). In case of error, all partially allocated tables are */
  88. /* released. */
  89. /* */
  90. FT_LOCAL_DEF( FT_Error )
  91. tt_face_load_charmap( TT_Face face,
  92. TT_CMapTable cmap,
  93. FT_Stream stream )
  94. {
  95. FT_Error error;
  96. FT_Memory memory;
  97. FT_UShort num_SH, num_Seg, i;
  98. FT_ULong j, n;
  99. FT_UShort u, l;
  100. TT_CMap0 cmap0;
  101. TT_CMap2 cmap2;
  102. TT_CMap4 cmap4;
  103. TT_CMap6 cmap6;
  104. TT_CMap8_12 cmap8_12;
  105. TT_CMap10 cmap10;
  106. TT_CMap2SubHeader cmap2sub;
  107. TT_CMap4Segment segments;
  108. TT_CMapGroup groups;
  109. if ( cmap->loaded )
  110. return SFNT_Err_Ok;
  111. memory = stream->memory;
  112. if ( FT_STREAM_SEEK( cmap->offset ) )
  113. return error;
  114. switch ( cmap->format )
  115. {
  116. case 0:
  117. cmap0 = &cmap->c.cmap0;
  118. if ( FT_READ_USHORT( cmap0->language ) ||
  119. FT_ALLOC( cmap0->glyphIdArray, 256L ) ||
  120. FT_STREAM_READ( cmap0->glyphIdArray, 256L ) )
  121. goto Fail;
  122. cmap->get_index = code_to_index0;
  123. cmap->get_next_char = code_to_next0;
  124. break;
  125. case 2:
  126. num_SH = 0;
  127. cmap2 = &cmap->c.cmap2;
  128. /* allocate subheader keys */
  129. if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) ||
  130. FT_FRAME_ENTER( 2L + 512L ) )
  131. goto Fail;
  132. cmap2->language = FT_GET_USHORT();
  133. for ( i = 0; i < 256; i++ )
  134. {
  135. u = (FT_UShort)( FT_GET_USHORT() / 8 );
  136. cmap2->subHeaderKeys[i] = u;
  137. if ( num_SH < u )
  138. num_SH = u;
  139. }
  140. FT_FRAME_EXIT();
  141. /* load subheaders */
  142. cmap2->numGlyphId = l = (FT_UShort)(
  143. ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 );
  144. if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) ||
  145. FT_FRAME_ENTER( ( num_SH + 1 ) * 8L ) )
  146. {
  147. FT_FREE( cmap2->subHeaderKeys );
  148. goto Fail;
  149. }
  150. cmap2sub = cmap2->subHeaders;
  151. for ( i = 0; i <= num_SH; i++ )
  152. {
  153. cmap2sub->firstCode = FT_GET_USHORT();
  154. cmap2sub->entryCount = FT_GET_USHORT();
  155. cmap2sub->idDelta = FT_GET_SHORT();
  156. /* we apply the location offset immediately */
  157. cmap2sub->idRangeOffset = (FT_UShort)(
  158. FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 );
  159. cmap2sub++;
  160. }
  161. FT_FRAME_EXIT();
  162. /* load glyph IDs */
  163. if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) ||
  164. FT_FRAME_ENTER( l * 2L ) )
  165. {
  166. FT_FREE( cmap2->subHeaders );
  167. FT_FREE( cmap2->subHeaderKeys );
  168. goto Fail;
  169. }
  170. for ( i = 0; i < l; i++ )
  171. cmap2->glyphIdArray[i] = FT_GET_USHORT();
  172. FT_FRAME_EXIT();
  173. cmap->get_index = code_to_index2;
  174. cmap->get_next_char = code_to_next2;
  175. break;
  176. case 4:
  177. cmap4 = &cmap->c.cmap4;
  178. /* load header */
  179. if ( FT_FRAME_ENTER( 10L ) )
  180. goto Fail;
  181. cmap4->language = FT_GET_USHORT();
  182. cmap4->segCountX2 = FT_GET_USHORT();
  183. cmap4->searchRange = FT_GET_USHORT();
  184. cmap4->entrySelector = FT_GET_USHORT();
  185. cmap4->rangeShift = FT_GET_USHORT();
  186. num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );
  187. FT_FRAME_EXIT();
  188. /* load segments */
  189. if ( FT_NEW_ARRAY( cmap4->segments, num_Seg ) ||
  190. FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) )
  191. goto Fail;
  192. segments = cmap4->segments;
  193. for ( i = 0; i < num_Seg; i++ )
  194. segments[i].endCount = FT_GET_USHORT();
  195. (void)FT_GET_USHORT();
  196. for ( i = 0; i < num_Seg; i++ )
  197. segments[i].startCount = FT_GET_USHORT();
  198. for ( i = 0; i < num_Seg; i++ )
  199. segments[i].idDelta = FT_GET_SHORT();
  200. for ( i = 0; i < num_Seg; i++ )
  201. segments[i].idRangeOffset = FT_GET_USHORT();
  202. FT_FRAME_EXIT();
  203. cmap4->numGlyphId = l = (FT_UShort)(
  204. ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 );
  205. /* load IDs */
  206. if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) ||
  207. FT_FRAME_ENTER( l * 2L ) )
  208. {
  209. FT_FREE( cmap4->segments );
  210. goto Fail;
  211. }
  212. for ( i = 0; i < l; i++ )
  213. cmap4->glyphIdArray[i] = FT_GET_USHORT();
  214. FT_FRAME_EXIT();
  215. cmap4->last_segment = cmap4->segments;
  216. cmap->get_index = code_to_index4;
  217. cmap->get_next_char = code_to_next4;
  218. break;
  219. case 6:
  220. cmap6 = &cmap->c.cmap6;
  221. if ( FT_FRAME_ENTER( 6L ) )
  222. goto Fail;
  223. cmap6->language = FT_GET_USHORT();
  224. cmap6->firstCode = FT_GET_USHORT();
  225. cmap6->entryCount = FT_GET_USHORT();
  226. FT_FRAME_EXIT();
  227. l = cmap6->entryCount;
  228. if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) ||
  229. FT_FRAME_ENTER( l * 2L ) )
  230. goto Fail;
  231. for ( i = 0; i < l; i++ )
  232. cmap6->glyphIdArray[i] = FT_GET_USHORT();
  233. FT_FRAME_EXIT();
  234. cmap->get_index = code_to_index6;
  235. cmap->get_next_char = code_to_next6;
  236. break;
  237. case 8:
  238. case 12:
  239. cmap8_12 = &cmap->c.cmap8_12;
  240. if ( FT_FRAME_ENTER( 8L ) )
  241. goto Fail;
  242. cmap->length = FT_GET_ULONG();
  243. cmap8_12->language = FT_GET_ULONG();
  244. FT_FRAME_EXIT();
  245. if ( cmap->format == 8 )
  246. if ( FT_STREAM_SKIP( 8192L ) )
  247. goto Fail;
  248. if ( FT_READ_ULONG( cmap8_12->nGroups ) )
  249. goto Fail;
  250. n = cmap8_12->nGroups;
  251. if ( FT_NEW_ARRAY( cmap8_12->groups, n ) ||
  252. FT_FRAME_ENTER( n * 3 * 4L ) )
  253. goto Fail;
  254. groups = cmap8_12->groups;
  255. for ( j = 0; j < n; j++ )
  256. {
  257. groups[j].startCharCode = FT_GET_ULONG();
  258. groups[j].endCharCode = FT_GET_ULONG();
  259. groups[j].startGlyphID = FT_GET_ULONG();
  260. }
  261. FT_FRAME_EXIT();
  262. cmap8_12->last_group = cmap8_12->groups;
  263. cmap->get_index = code_to_index8_12;
  264. cmap->get_next_char = code_to_next8_12;
  265. break;
  266. case 10:
  267. cmap10 = &cmap->c.cmap10;
  268. if ( FT_FRAME_ENTER( 16L ) )
  269. goto Fail;
  270. cmap->length = FT_GET_ULONG();
  271. cmap10->language = FT_GET_ULONG();
  272. cmap10->startCharCode = FT_GET_ULONG();
  273. cmap10->numChars = FT_GET_ULONG();
  274. FT_FRAME_EXIT();
  275. n = cmap10->numChars;
  276. if ( FT_NEW_ARRAY( cmap10->glyphs, n ) ||
  277. FT_FRAME_ENTER( n * 2L ) )
  278. goto Fail;
  279. for ( j = 0; j < n; j++ )
  280. cmap10->glyphs[j] = FT_GET_USHORT();
  281. FT_FRAME_EXIT();
  282. cmap->get_index = code_to_index10;
  283. cmap->get_next_char = code_to_next10;
  284. break;
  285. default: /* corrupt character mapping table */
  286. return SFNT_Err_Invalid_CharMap_Format;
  287. }
  288. return SFNT_Err_Ok;
  289. Fail:
  290. tt_face_free_charmap( face, cmap );
  291. return error;
  292. }
  293. /*************************************************************************/
  294. /* */
  295. /* <Function> */
  296. /* tt_face_free_charmap */
  297. /* */
  298. /* <Description> */
  299. /* Destroys a character mapping table. */
  300. /* */
  301. /* <Input> */
  302. /* face :: A handle to the parent face object. */
  303. /* */
  304. /* cmap :: A handle to a cmap object. */
  305. /* */
  306. /* <Return> */
  307. /* FreeType error code. 0 means success. */
  308. /* */
  309. FT_LOCAL_DEF( FT_Error )
  310. tt_face_free_charmap( TT_Face face,
  311. TT_CMapTable cmap )
  312. {
  313. FT_Memory memory;
  314. if ( !cmap )
  315. return SFNT_Err_Ok;
  316. memory = face->root.driver->root.memory;
  317. switch ( cmap->format )
  318. {
  319. case 0:
  320. FT_FREE( cmap->c.cmap0.glyphIdArray );
  321. break;
  322. case 2:
  323. FT_FREE( cmap->c.cmap2.subHeaderKeys );
  324. FT_FREE( cmap->c.cmap2.subHeaders );
  325. FT_FREE( cmap->c.cmap2.glyphIdArray );
  326. break;
  327. case 4:
  328. FT_FREE( cmap->c.cmap4.segments );
  329. FT_FREE( cmap->c.cmap4.glyphIdArray );
  330. cmap->c.cmap4.segCountX2 = 0;
  331. break;
  332. case 6:
  333. FT_FREE( cmap->c.cmap6.glyphIdArray );
  334. cmap->c.cmap6.entryCount = 0;
  335. break;
  336. case 8:
  337. case 12:
  338. FT_FREE( cmap->c.cmap8_12.groups );
  339. cmap->c.cmap8_12.nGroups = 0;
  340. break;
  341. case 10:
  342. FT_FREE( cmap->c.cmap10.glyphs );
  343. cmap->c.cmap10.numChars = 0;
  344. break;
  345. default:
  346. /* invalid table format, do nothing */
  347. ;
  348. }
  349. cmap->loaded = FALSE;
  350. return SFNT_Err_Ok;
  351. }
  352. /*************************************************************************/
  353. /* */
  354. /* <Function> */
  355. /* code_to_index0 */
  356. /* */
  357. /* <Description> */
  358. /* Converts the character code into a glyph index. Uses format 0. */
  359. /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */
  360. /* returned). */
  361. /* */
  362. /* <Input> */
  363. /* charCode :: The wanted character code. */
  364. /* */
  365. /* cmap0 :: A pointer to a cmap table in format 0. */
  366. /* */
  367. /* <Return> */
  368. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  369. /* */
  370. FT_CALLBACK_DEF( FT_UInt )
  371. code_to_index0( TT_CMapTable cmap,
  372. FT_ULong charCode )
  373. {
  374. TT_CMap0 cmap0 = &cmap->c.cmap0;
  375. return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
  376. }
  377. /*************************************************************************/
  378. /* */
  379. /* <Function> */
  380. /* code_to_next0 */
  381. /* */
  382. /* <Description> */
  383. /* Finds the next encoded character after the given one. Uses */
  384. /* format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0 */
  385. /* is returned). */
  386. /* */
  387. /* <Input> */
  388. /* charCode :: The wanted character code. */
  389. /* */
  390. /* cmap0 :: A pointer to a cmap table in format 0. */
  391. /* */
  392. /* <Return> */
  393. /* Next char code. 0 if no higher one is encoded. */
  394. /* */
  395. FT_CALLBACK_DEF( FT_ULong )
  396. code_to_next0( TT_CMapTable cmap,
  397. FT_ULong charCode )
  398. {
  399. TT_CMap0 cmap0 = &cmap->c.cmap0;
  400. while ( ++charCode <= 0xFF )
  401. if ( cmap0->glyphIdArray[charCode] )
  402. return ( charCode );
  403. return ( 0 );
  404. }
  405. /*************************************************************************/
  406. /* */
  407. /* <Function> */
  408. /* code_to_index2 */
  409. /* */
  410. /* <Description> */
  411. /* Converts the character code into a glyph index. Uses format 2. */
  412. /* */
  413. /* <Input> */
  414. /* charCode :: The wanted character code. */
  415. /* */
  416. /* cmap2 :: A pointer to a cmap table in format 2. */
  417. /* */
  418. /* <Return> */
  419. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  420. /* */
  421. FT_CALLBACK_DEF( FT_UInt )
  422. code_to_index2( TT_CMapTable cmap,
  423. FT_ULong charCode )
  424. {
  425. FT_UInt result, index1, offset;
  426. FT_UInt char_lo;
  427. FT_ULong char_hi;
  428. TT_CMap2SubHeader sh2;
  429. TT_CMap2 cmap2;
  430. cmap2 = &cmap->c.cmap2;
  431. result = 0;
  432. char_lo = (FT_UInt)( charCode & 0xFF );
  433. char_hi = charCode >> 8;
  434. if ( char_hi == 0 )
  435. {
  436. /* an 8-bit character code -- we use the subHeader 0 in this case */
  437. /* to test whether the character code is in the charmap */
  438. index1 = cmap2->subHeaderKeys[char_lo];
  439. if ( index1 != 0 )
  440. return 0;
  441. }
  442. else
  443. {
  444. /* a 16-bit character code */
  445. index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
  446. if ( index1 == 0 )
  447. return 0;
  448. }
  449. sh2 = cmap2->subHeaders + index1;
  450. char_lo -= sh2->firstCode;
  451. if ( char_lo < (FT_UInt)sh2->entryCount )
  452. {
  453. offset = sh2->idRangeOffset / 2 + char_lo;
  454. if ( offset < (FT_UInt)cmap2->numGlyphId )
  455. {
  456. result = cmap2->glyphIdArray[offset];
  457. if ( result )
  458. result = ( result + sh2->idDelta ) & 0xFFFFU;
  459. }
  460. }
  461. return result;
  462. }
  463. /*************************************************************************/
  464. /* */
  465. /* <Function> */
  466. /* code_to_next2 */
  467. /* */
  468. /* <Description> */
  469. /* Find the next encoded character. Uses format 2. */
  470. /* */
  471. /* <Input> */
  472. /* charCode :: The wanted character code. */
  473. /* */
  474. /* cmap2 :: A pointer to a cmap table in format 2. */
  475. /* */
  476. /* <Return> */
  477. /* Next encoded character. 0 if none exists. */
  478. /* */
  479. FT_CALLBACK_DEF( FT_ULong )
  480. code_to_next2( TT_CMapTable cmap,
  481. FT_ULong charCode )
  482. {
  483. FT_UInt index1, offset;
  484. FT_UInt char_lo;
  485. FT_ULong char_hi;
  486. TT_CMap2SubHeader sh2;
  487. TT_CMap2 cmap2;
  488. cmap2 = &cmap->c.cmap2;
  489. charCode++;
  490. /*
  491. * This is relatively simplistic -- look for a subHeader containing
  492. * glyphs and then walk to the first glyph in that subHeader.
  493. */
  494. while ( charCode < 0x10000L )
  495. {
  496. char_lo = (FT_UInt)( charCode & 0xFF );
  497. char_hi = charCode >> 8;
  498. if ( char_hi == 0 )
  499. {
  500. /* an 8-bit character code -- we use the subHeader 0 in this case */
  501. /* to test whether the character code is in the charmap */
  502. index1 = cmap2->subHeaderKeys[char_lo];
  503. if ( index1 != 0 )
  504. {
  505. charCode++;
  506. continue;
  507. }
  508. }
  509. else
  510. {
  511. /* a 16-bit character code */
  512. index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
  513. if ( index1 == 0 )
  514. {
  515. charCode = ( char_hi + 1 ) << 8;
  516. continue;
  517. }
  518. }
  519. sh2 = cmap2->subHeaders + index1;
  520. char_lo -= sh2->firstCode;
  521. if ( char_lo > (FT_UInt)sh2->entryCount )
  522. {
  523. charCode = ( char_hi + 1 ) << 8;
  524. continue;
  525. }
  526. offset = sh2->idRangeOffset / 2 + char_lo;
  527. if ( offset >= (FT_UInt)cmap2->numGlyphId ||
  528. cmap2->glyphIdArray[offset] == 0 )
  529. {
  530. charCode++;
  531. continue;
  532. }
  533. return charCode;
  534. }
  535. return 0;
  536. }
  537. /*************************************************************************/
  538. /* */
  539. /* <Function> */
  540. /* code_to_index4 */
  541. /* */
  542. /* <Description> */
  543. /* Converts the character code into a glyph index. Uses format 4. */
  544. /* */
  545. /* <Input> */
  546. /* charCode :: The wanted character code. */
  547. /* */
  548. /* cmap4 :: A pointer to a cmap table in format 4. */
  549. /* */
  550. /* <Return> */
  551. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  552. /* */
  553. FT_CALLBACK_DEF( FT_UInt )
  554. code_to_index4( TT_CMapTable cmap,
  555. FT_ULong charCode )
  556. {
  557. FT_UInt result, index1, segCount;
  558. TT_CMap4 cmap4;
  559. TT_CMap4SegmentRec *seg4, *limit;
  560. cmap4 = &cmap->c.cmap4;
  561. result = 0;
  562. segCount = cmap4->segCountX2 / 2;
  563. limit = cmap4->segments + segCount;
  564. /* first, check against the last used segment */
  565. seg4 = cmap4->last_segment;
  566. /* the following is equivalent to performing two tests, as in */
  567. /* */
  568. /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
  569. /* */
  570. /* This is a bit strange, but it is faster, and the idea behind the */
  571. /* cache is to significantly speed up charcode to glyph index */
  572. /* conversion. */
  573. if ( (FT_ULong)( charCode - seg4->startCount ) <
  574. (FT_ULong)( seg4->endCount - seg4->startCount ) )
  575. goto Found1;
  576. for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
  577. {
  578. /* the ranges are sorted in increasing order. If we are out of */
  579. /* the range here, the char code isn't in the charmap, so exit. */
  580. if ( charCode > (FT_UInt)seg4->endCount )
  581. continue;
  582. if ( charCode >= (FT_UInt)seg4->startCount )
  583. goto Found;
  584. }
  585. return 0;
  586. Found:
  587. cmap4->last_segment = seg4;
  588. Found1:
  589. /* if the idRangeOffset is 0, we can compute the glyph index */
  590. /* directly */
  591. if ( seg4->idRangeOffset == 0 )
  592. result = (FT_UInt)( charCode + seg4->idDelta ) & 0xFFFFU;
  593. else
  594. {
  595. /* otherwise, we must use the glyphIdArray to do it */
  596. index1 = (FT_UInt)( seg4->idRangeOffset / 2
  597. + ( charCode - seg4->startCount )
  598. + ( seg4 - cmap4->segments )
  599. - segCount );
  600. if ( index1 < (FT_UInt)cmap4->numGlyphId &&
  601. cmap4->glyphIdArray[index1] != 0 )
  602. result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFFU;
  603. }
  604. return result;
  605. }
  606. /*************************************************************************/
  607. /* */
  608. /* <Function> */
  609. /* code_to_next4 */
  610. /* */
  611. /* <Description> */
  612. /* Find the next encoded character. Uses format 4. */
  613. /* */
  614. /* <Input> */
  615. /* charCode :: The wanted character code. */
  616. /* */
  617. /* cmap :: A pointer to a cmap table in format 4. */
  618. /* */
  619. /* <Return> */
  620. /* Next encoded character. 0 if none exists. */
  621. /* */
  622. FT_CALLBACK_DEF( FT_ULong )
  623. code_to_next4( TT_CMapTable cmap,
  624. FT_ULong charCode )
  625. {
  626. FT_UInt index1, segCount;
  627. TT_CMap4 cmap4;
  628. TT_CMap4SegmentRec *seg4, *limit;
  629. cmap4 = &cmap->c.cmap4;
  630. segCount = cmap4->segCountX2 / 2;
  631. limit = cmap4->segments + segCount;
  632. charCode++;
  633. for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
  634. {
  635. /* The ranges are sorted in increasing order. If we are out of */
  636. /* the range here, the char code isn't in the charmap, so exit. */
  637. if ( charCode <= (FT_UInt)seg4->endCount )
  638. goto Found;
  639. }
  640. return 0;
  641. Found:
  642. if ( charCode < (FT_ULong) seg4->startCount )
  643. charCode = seg4->startCount;
  644. /* if the idRangeOffset is 0, all chars in the map exist */
  645. if ( seg4->idRangeOffset == 0 )
  646. return ( charCode );
  647. while ( charCode <= (FT_UInt) seg4->endCount )
  648. {
  649. /* otherwise, we must use the glyphIdArray to do it */
  650. index1 = (FT_UInt)( seg4->idRangeOffset / 2
  651. + ( charCode - seg4->startCount )
  652. + ( seg4 - cmap4->segments )
  653. - segCount );
  654. if ( index1 < (FT_UInt)cmap4->numGlyphId &&
  655. cmap4->glyphIdArray[index1] != 0 )
  656. return ( charCode );
  657. charCode++;
  658. }
  659. return 0;
  660. }
  661. /*************************************************************************/
  662. /* */
  663. /* <Function> */
  664. /* code_to_index6 */
  665. /* */
  666. /* <Description> */
  667. /* Converts the character code into a glyph index. Uses format 6. */
  668. /* */
  669. /* <Input> */
  670. /* charCode :: The wanted character code. */
  671. /* */
  672. /* cmap6 :: A pointer to a cmap table in format 6. */
  673. /* */
  674. /* <Return> */
  675. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  676. /* */
  677. FT_CALLBACK_DEF( FT_UInt )
  678. code_to_index6( TT_CMapTable cmap,
  679. FT_ULong charCode )
  680. {
  681. TT_CMap6 cmap6;
  682. FT_UInt result = 0;
  683. cmap6 = &cmap->c.cmap6;
  684. charCode -= cmap6->firstCode;
  685. if ( charCode < (FT_UInt)cmap6->entryCount )
  686. result = cmap6->glyphIdArray[charCode];
  687. return result;
  688. }
  689. /*************************************************************************/
  690. /* */
  691. /* <Function> */
  692. /* code_to_next6 */
  693. /* */
  694. /* <Description> */
  695. /* Find the next encoded character. Uses format 6. */
  696. /* */
  697. /* <Input> */
  698. /* charCode :: The wanted character code. */
  699. /* */
  700. /* cmap :: A pointer to a cmap table in format 6. */
  701. /* */
  702. /* <Return> */
  703. /* Next encoded character. 0 if none exists. */
  704. /* */
  705. FT_CALLBACK_DEF( FT_ULong )
  706. code_to_next6( TT_CMapTable cmap,
  707. FT_ULong charCode )
  708. {
  709. TT_CMap6 cmap6;
  710. charCode++;
  711. cmap6 = &cmap->c.cmap6;
  712. if ( charCode < (FT_ULong) cmap6->firstCode )
  713. charCode = cmap6->firstCode;
  714. charCode -= cmap6->firstCode;
  715. while ( charCode < (FT_UInt)cmap6->entryCount )
  716. {
  717. if ( cmap6->glyphIdArray[charCode] != 0 )
  718. return charCode + cmap6->firstCode;
  719. charCode++;
  720. }
  721. return 0;
  722. }
  723. /*************************************************************************/
  724. /* */
  725. /* <Function> */
  726. /* code_to_index8_12 */
  727. /* */
  728. /* <Description> */
  729. /* Converts the (possibly 32bit) character code into a glyph index. */
  730. /* Uses format 8 or 12. */
  731. /* */
  732. /* <Input> */
  733. /* charCode :: The wanted character code. */
  734. /* */
  735. /* cmap8_12 :: A pointer to a cmap table in format 8 or 12. */
  736. /* */
  737. /* <Return> */
  738. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  739. /* */
  740. FT_CALLBACK_DEF( FT_UInt )
  741. code_to_index8_12( TT_CMapTable cmap,
  742. FT_ULong charCode )
  743. {
  744. TT_CMap8_12 cmap8_12;
  745. TT_CMapGroupRec *group, *limit;
  746. cmap8_12 = &cmap->c.cmap8_12;
  747. limit = cmap8_12->groups + cmap8_12->nGroups;
  748. /* first, check against the last used group */
  749. group = cmap8_12->last_group;
  750. /* the following is equivalent to performing two tests, as in */
  751. /* */
  752. /* if ( charCode >= group->startCharCode && */
  753. /* charCode <= group->endCharCode ) */
  754. /* */
  755. /* This is a bit strange, but it is faster, and the idea behind the */
  756. /* cache is to significantly speed up charcode to glyph index */
  757. /* conversion. */
  758. if ( (FT_ULong)( charCode - group->startCharCode ) <
  759. (FT_ULong)( group->endCharCode - group->startCharCode ) )
  760. goto Found1;
  761. for ( group = cmap8_12->groups; group < limit; group++ )
  762. {
  763. /* the ranges are sorted in increasing order. If we are out of */
  764. /* the range here, the char code isn't in the charmap, so exit. */
  765. if ( charCode > group->endCharCode )
  766. continue;
  767. if ( charCode >= group->startCharCode )
  768. goto Found;
  769. }
  770. return 0;
  771. Found:
  772. cmap8_12->last_group = group;
  773. Found1:
  774. return (FT_UInt)( group->startGlyphID +
  775. ( charCode - group->startCharCode ) );
  776. }
  777. /*************************************************************************/
  778. /* */
  779. /* <Function> */
  780. /* code_to_next8_12 */
  781. /* */
  782. /* <Description> */
  783. /* Find the next encoded character. Uses format 8 or 12. */
  784. /* */
  785. /* <Input> */
  786. /* charCode :: The wanted character code. */
  787. /* */
  788. /* cmap :: A pointer to a cmap table in format 8 or 12. */
  789. /* */
  790. /* <Return> */
  791. /* Next encoded character. 0 if none exists. */
  792. /* */
  793. FT_CALLBACK_DEF( FT_ULong )
  794. code_to_next8_12( TT_CMapTable cmap,
  795. FT_ULong charCode )
  796. {
  797. TT_CMap8_12 cmap8_12;
  798. TT_CMapGroupRec *group, *limit;
  799. charCode++;
  800. cmap8_12 = &cmap->c.cmap8_12;
  801. limit = cmap8_12->groups + cmap8_12->nGroups;
  802. for ( group = cmap8_12->groups; group < limit; group++ )
  803. {
  804. /* the ranges are sorted in increasing order. If we are out of */
  805. /* the range here, the char code isn't in the charmap, so exit. */
  806. if ( charCode <= group->endCharCode )
  807. goto Found;
  808. }
  809. return 0;
  810. Found:
  811. if ( charCode < group->startCharCode )
  812. charCode = group->startCharCode;
  813. return charCode;
  814. }
  815. /*************************************************************************/
  816. /* */
  817. /* <Function> */
  818. /* code_to_index10 */
  819. /* */
  820. /* <Description> */
  821. /* Converts the (possibly 32bit) character code into a glyph index. */
  822. /* Uses format 10. */
  823. /* */
  824. /* <Input> */
  825. /* charCode :: The wanted character code. */
  826. /* */
  827. /* cmap10 :: A pointer to a cmap table in format 10. */
  828. /* */
  829. /* <Return> */
  830. /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
  831. /* */
  832. FT_CALLBACK_DEF( FT_UInt )
  833. code_to_index10( TT_CMapTable cmap,
  834. FT_ULong charCode )
  835. {
  836. TT_CMap10 cmap10;
  837. FT_UInt result = 0;
  838. cmap10 = &cmap->c.cmap10;
  839. charCode -= cmap10->startCharCode;
  840. /* the overflow trick for comparison works here also since the number */
  841. /* of glyphs (even if numChars is specified as ULong in the specs) in */
  842. /* an OpenType font is limited to 64k */
  843. if ( charCode < cmap10->numChars )
  844. result = cmap10->glyphs[charCode];
  845. return result;
  846. }
  847. /*************************************************************************/
  848. /* */
  849. /* <Function> */
  850. /* code_to_next10 */
  851. /* */
  852. /* <Description> */
  853. /* Find the next encoded character. Uses format 10. */
  854. /* */
  855. /* <Input> */
  856. /* charCode :: The wanted character code. */
  857. /* */
  858. /* cmap :: A pointer to a cmap table in format 10. */
  859. /* */
  860. /* <Return> */
  861. /* Next encoded character. 0 if none exists. */
  862. /* */
  863. FT_CALLBACK_DEF( FT_ULong )
  864. code_to_next10( TT_CMapTable cmap,
  865. FT_ULong charCode )
  866. {
  867. TT_CMap10 cmap10;
  868. charCode++;
  869. cmap10 = &cmap->c.cmap10;
  870. if ( charCode < cmap10->startCharCode )
  871. charCode = cmap10->startCharCode;
  872. charCode -= cmap10->startCharCode;
  873. /* the overflow trick for comparison works here also since the number */
  874. /* of glyphs (even if numChars is specified as ULong in the specs) in */
  875. /* an OpenType font is limited to 64k */
  876. while ( charCode < cmap10->numChars )
  877. {
  878. if ( cmap10->glyphs[charCode] )
  879. return ( charCode + cmap10->startCharCode );
  880. charCode++;
  881. }
  882. return 0;
  883. }
  884. /* END */