pdf_cmap.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * The CMap data structure here is constructed on the fly by
  3. * adding simple range-to-range mappings. Then the data structure
  4. * is optimized to contain both range-to-range and range-to-table
  5. * lookups.
  6. *
  7. * Any one-to-many mappings are inserted as one-to-table
  8. * lookups in the beginning, and are not affected by the optimization
  9. * stage.
  10. *
  11. * There is a special function to add a 256-length range-to-table mapping.
  12. * The ranges do not have to be added in order.
  13. *
  14. * This code can be a lot simpler if we don't care about wasting memory,
  15. * or can trust the parser to give us optimal mappings.
  16. */
  17. #include "fitz-internal.h"
  18. #include "mupdf-internal.h"
  19. /* Macros for accessing the combined extent_flags field */
  20. #define pdf_range_high(r) ((r)->low + ((r)->extent_flags >> 2))
  21. #define pdf_range_flags(r) ((r)->extent_flags & 3)
  22. #define pdf_range_set_high(r, h) \
  23. ((r)->extent_flags = (((r)->extent_flags & 3) | ((h - (r)->low) << 2)))
  24. #define pdf_range_set_flags(r, f) \
  25. ((r)->extent_flags = (((r)->extent_flags & ~3) | f))
  26. /*
  27. * Allocate, destroy and simple parameters.
  28. */
  29. void
  30. pdf_free_cmap_imp(fz_context *ctx, fz_storable *cmap_)
  31. {
  32. pdf_cmap *cmap = (pdf_cmap *)cmap_;
  33. if (cmap->usecmap)
  34. pdf_drop_cmap(ctx, cmap->usecmap);
  35. fz_free(ctx, cmap->ranges);
  36. fz_free(ctx, cmap->table);
  37. fz_free(ctx, cmap);
  38. }
  39. pdf_cmap *
  40. pdf_new_cmap(fz_context *ctx)
  41. {
  42. pdf_cmap *cmap;
  43. cmap = fz_malloc_struct(ctx, pdf_cmap);
  44. FZ_INIT_STORABLE(cmap, 1, pdf_free_cmap_imp);
  45. strcpy(cmap->cmap_name, "");
  46. strcpy(cmap->usecmap_name, "");
  47. cmap->usecmap = NULL;
  48. cmap->wmode = 0;
  49. cmap->codespace_len = 0;
  50. cmap->rlen = 0;
  51. cmap->rcap = 0;
  52. cmap->ranges = NULL;
  53. cmap->tlen = 0;
  54. cmap->tcap = 0;
  55. cmap->table = NULL;
  56. return cmap;
  57. }
  58. /* Could be a macro for speed */
  59. pdf_cmap *
  60. pdf_keep_cmap(fz_context *ctx, pdf_cmap *cmap)
  61. {
  62. return (pdf_cmap *)fz_keep_storable(ctx, &cmap->storable);
  63. }
  64. /* Could be a macro for speed */
  65. void
  66. pdf_drop_cmap(fz_context *ctx, pdf_cmap *cmap)
  67. {
  68. fz_drop_storable(ctx, &cmap->storable);
  69. }
  70. void
  71. pdf_set_usecmap(fz_context *ctx, pdf_cmap *cmap, pdf_cmap *usecmap)
  72. {
  73. int i;
  74. if (cmap->usecmap)
  75. pdf_drop_cmap(ctx, cmap->usecmap);
  76. cmap->usecmap = pdf_keep_cmap(ctx, usecmap);
  77. if (cmap->codespace_len == 0)
  78. {
  79. cmap->codespace_len = usecmap->codespace_len;
  80. for (i = 0; i < usecmap->codespace_len; i++)
  81. cmap->codespace[i] = usecmap->codespace[i];
  82. }
  83. }
  84. int
  85. pdf_cmap_wmode(fz_context *ctx, pdf_cmap *cmap)
  86. {
  87. return cmap->wmode;
  88. }
  89. void
  90. pdf_set_cmap_wmode(fz_context *ctx, pdf_cmap *cmap, int wmode)
  91. {
  92. cmap->wmode = wmode;
  93. }
  94. #ifndef NDEBUG
  95. void
  96. pdf_print_cmap(fz_context *ctx, pdf_cmap *cmap)
  97. {
  98. int i, k, n;
  99. printf("cmap $%p /%s {\n", (void *) cmap, cmap->cmap_name);
  100. if (cmap->usecmap_name[0])
  101. printf("\tusecmap /%s\n", cmap->usecmap_name);
  102. if (cmap->usecmap)
  103. printf("\tusecmap $%p\n", (void *) cmap->usecmap);
  104. printf("\twmode %d\n", cmap->wmode);
  105. printf("\tcodespaces {\n");
  106. for (i = 0; i < cmap->codespace_len; i++)
  107. {
  108. printf("\t\t<%x> <%x>\n", cmap->codespace[i].low, cmap->codespace[i].high);
  109. }
  110. printf("\t}\n");
  111. printf("\tranges (%d,%d) {\n", cmap->rlen, cmap->tlen);
  112. for (i = 0; i < cmap->rlen; i++)
  113. {
  114. pdf_range *r = &cmap->ranges[i];
  115. printf("\t\t<%04x> <%04x> ", r->low, pdf_range_high(r));
  116. if (pdf_range_flags(r) == PDF_CMAP_TABLE)
  117. {
  118. printf("[ ");
  119. for (k = 0; k < pdf_range_high(r) - r->low + 1; k++)
  120. printf("%d ", cmap->table[r->offset + k]);
  121. printf("]\n");
  122. }
  123. else if (pdf_range_flags(r) == PDF_CMAP_MULTI)
  124. {
  125. printf("< ");
  126. n = cmap->table[r->offset];
  127. for (k = 0; k < n; k++)
  128. printf("%04x ", cmap->table[r->offset + 1 + k]);
  129. printf(">\n");
  130. }
  131. else
  132. printf("%d\n", r->offset);
  133. }
  134. printf("\t}\n}\n");
  135. }
  136. #endif
  137. /*
  138. * Add a codespacerange section.
  139. * These ranges are used by pdf_decode_cmap to decode
  140. * multi-byte encoded strings.
  141. */
  142. void
  143. pdf_add_codespace(fz_context *ctx, pdf_cmap *cmap, int low, int high, int n)
  144. {
  145. if (cmap->codespace_len + 1 == nelem(cmap->codespace))
  146. {
  147. fz_warn(ctx, "assert: too many code space ranges");
  148. return;
  149. }
  150. cmap->codespace[cmap->codespace_len].n = n;
  151. cmap->codespace[cmap->codespace_len].low = low;
  152. cmap->codespace[cmap->codespace_len].high = high;
  153. cmap->codespace_len ++;
  154. }
  155. /*
  156. * Add an integer to the table.
  157. */
  158. static void
  159. add_table(fz_context *ctx, pdf_cmap *cmap, int value)
  160. {
  161. if (cmap->tlen >= USHRT_MAX + 1)
  162. {
  163. fz_warn(ctx, "cmap table is full; ignoring additional entries");
  164. return;
  165. }
  166. if (cmap->tlen + 1 > cmap->tcap)
  167. {
  168. int new_cap = cmap->tcap > 1 ? (cmap->tcap * 3) / 2 : 256;
  169. cmap->table = fz_resize_array(ctx, cmap->table, new_cap, sizeof(unsigned short));
  170. cmap->tcap = new_cap;
  171. }
  172. cmap->table[cmap->tlen++] = value;
  173. }
  174. /*
  175. * Add a range.
  176. */
  177. static void
  178. add_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int flag, int offset)
  179. {
  180. /* Sanity check ranges */
  181. if (low < 0 || low > 65535 || high < 0 || high > 65535 || low > high)
  182. {
  183. fz_warn(ctx, "range limits out of range in cmap %s", cmap->cmap_name);
  184. return;
  185. }
  186. /* If the range is too large to be represented, split it */
  187. if (high - low > 0x3fff)
  188. {
  189. add_range(ctx, cmap, low, low+0x3fff, flag, offset);
  190. add_range(ctx, cmap, low+0x3fff, high, flag, offset+0x3fff);
  191. return;
  192. }
  193. if (cmap->rlen + 1 > cmap->rcap)
  194. {
  195. int new_cap = cmap->rcap > 1 ? (cmap->rcap * 3) / 2 : 256;
  196. cmap->ranges = fz_resize_array(ctx, cmap->ranges, new_cap, sizeof(pdf_range));
  197. cmap->rcap = new_cap;
  198. }
  199. cmap->ranges[cmap->rlen].low = low;
  200. pdf_range_set_high(&cmap->ranges[cmap->rlen], high);
  201. pdf_range_set_flags(&cmap->ranges[cmap->rlen], flag);
  202. cmap->ranges[cmap->rlen].offset = offset;
  203. cmap->rlen ++;
  204. }
  205. /*
  206. * Add a range-to-table mapping.
  207. */
  208. void
  209. pdf_map_range_to_table(fz_context *ctx, pdf_cmap *cmap, int low, int *table, int len)
  210. {
  211. int i;
  212. int high = low + len;
  213. int offset = cmap->tlen;
  214. if (cmap->tlen + len >= USHRT_MAX + 1)
  215. fz_warn(ctx, "cannot map range to table; table is full");
  216. else
  217. {
  218. for (i = 0; i < len; i++)
  219. add_table(ctx, cmap, table[i]);
  220. add_range(ctx, cmap, low, high, PDF_CMAP_TABLE, offset);
  221. }
  222. }
  223. /*
  224. * Add a range of contiguous one-to-one mappings (ie 1..5 maps to 21..25)
  225. */
  226. void
  227. pdf_map_range_to_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int offset)
  228. {
  229. add_range(ctx, cmap, low, high, high - low == 0 ? PDF_CMAP_SINGLE : PDF_CMAP_RANGE, offset);
  230. }
  231. /*
  232. * Add a single one-to-many mapping.
  233. */
  234. void
  235. pdf_map_one_to_many(fz_context *ctx, pdf_cmap *cmap, int low, int *values, int len)
  236. {
  237. int offset, i;
  238. if (len == 1)
  239. {
  240. add_range(ctx, cmap, low, low, PDF_CMAP_SINGLE, values[0]);
  241. return;
  242. }
  243. if (len > 8)
  244. {
  245. fz_warn(ctx, "one to many mapping is too large (%d); truncating", len);
  246. len = 8;
  247. }
  248. if (len == 2 &&
  249. values[0] >= 0xD800 && values[0] <= 0xDBFF &&
  250. values[1] >= 0xDC00 && values[1] <= 0xDFFF)
  251. {
  252. fz_warn(ctx, "ignoring surrogate pair mapping in cmap %s", cmap->cmap_name);
  253. return;
  254. }
  255. if (cmap->tlen + len + 1 >= USHRT_MAX + 1)
  256. fz_warn(ctx, "cannot map one to many; table is full");
  257. else
  258. {
  259. offset = cmap->tlen;
  260. add_table(ctx, cmap, len);
  261. for (i = 0; i < len; i++)
  262. add_table(ctx, cmap, values[i]);
  263. add_range(ctx, cmap, low, low, PDF_CMAP_MULTI, offset);
  264. }
  265. }
  266. /*
  267. * Sort the input ranges.
  268. * Merge contiguous input ranges to range-to-range if the output is contiguous.
  269. * Merge contiguous input ranges to range-to-table if the output is random.
  270. */
  271. static int cmprange(const void *va, const void *vb)
  272. {
  273. return ((const pdf_range*)va)->low - ((const pdf_range*)vb)->low;
  274. }
  275. void
  276. pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap)
  277. {
  278. pdf_range *a; /* last written range on output */
  279. pdf_range *b; /* current range examined on input */
  280. if (cmap->rlen == 0)
  281. return;
  282. qsort(cmap->ranges, cmap->rlen, sizeof(pdf_range), cmprange);
  283. if (cmap->tlen >= USHRT_MAX + 1)
  284. {
  285. fz_warn(ctx, "cmap table is full; will not combine ranges");
  286. return;
  287. }
  288. a = cmap->ranges;
  289. b = cmap->ranges + 1;
  290. while (b < cmap->ranges + cmap->rlen)
  291. {
  292. /* ignore one-to-many mappings */
  293. if (pdf_range_flags(b) == PDF_CMAP_MULTI)
  294. {
  295. *(++a) = *b;
  296. }
  297. /* input contiguous */
  298. else if (pdf_range_high(a) + 1 == b->low)
  299. {
  300. /* output contiguous */
  301. if (pdf_range_high(a) - a->low + a->offset + 1 == b->offset)
  302. {
  303. /* SR -> R and SS -> R and RR -> R and RS -> R */
  304. if ((pdf_range_flags(a) == PDF_CMAP_SINGLE || pdf_range_flags(a) == PDF_CMAP_RANGE) && (pdf_range_high(b) - a->low <= 0x3fff))
  305. {
  306. pdf_range_set_flags(a, PDF_CMAP_RANGE);
  307. pdf_range_set_high(a, pdf_range_high(b));
  308. }
  309. /* LS -> L */
  310. else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff))
  311. {
  312. pdf_range_set_high(a, pdf_range_high(b));
  313. add_table(ctx, cmap, b->offset);
  314. }
  315. /* LR -> LR */
  316. else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_RANGE)
  317. {
  318. *(++a) = *b;
  319. }
  320. /* XX -> XX */
  321. else
  322. {
  323. *(++a) = *b;
  324. }
  325. }
  326. /* output separated */
  327. else
  328. {
  329. /* SS -> L */
  330. if (pdf_range_flags(a) == PDF_CMAP_SINGLE && pdf_range_flags(b) == PDF_CMAP_SINGLE)
  331. {
  332. pdf_range_set_flags(a, PDF_CMAP_TABLE);
  333. pdf_range_set_high(a, pdf_range_high(b));
  334. add_table(ctx, cmap, a->offset);
  335. add_table(ctx, cmap, b->offset);
  336. a->offset = cmap->tlen - 2;
  337. }
  338. /* LS -> L */
  339. else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff))
  340. {
  341. pdf_range_set_high(a, pdf_range_high(b));
  342. add_table(ctx, cmap, b->offset);
  343. }
  344. /* XX -> XX */
  345. else
  346. {
  347. *(++a) = *b;
  348. }
  349. }
  350. }
  351. /* input separated: XX -> XX */
  352. else
  353. {
  354. *(++a) = *b;
  355. }
  356. b ++;
  357. }
  358. cmap->rlen = a - cmap->ranges + 1;
  359. }
  360. /*
  361. * Lookup the mapping of a codepoint.
  362. */
  363. int
  364. pdf_lookup_cmap(pdf_cmap *cmap, int cpt)
  365. {
  366. int l = 0;
  367. int r = cmap->rlen - 1;
  368. int m;
  369. while (l <= r)
  370. {
  371. m = (l + r) >> 1;
  372. if (cpt < cmap->ranges[m].low)
  373. r = m - 1;
  374. else if (cpt > pdf_range_high(&cmap->ranges[m]))
  375. l = m + 1;
  376. else
  377. {
  378. int i = cpt - cmap->ranges[m].low + cmap->ranges[m].offset;
  379. if (pdf_range_flags(&cmap->ranges[m]) == PDF_CMAP_TABLE)
  380. return cmap->table[i];
  381. if (pdf_range_flags(&cmap->ranges[m]) == PDF_CMAP_MULTI)
  382. return -1; /* should use lookup_cmap_full */
  383. return i;
  384. }
  385. }
  386. if (cmap->usecmap)
  387. return pdf_lookup_cmap(cmap->usecmap, cpt);
  388. return -1;
  389. }
  390. int
  391. pdf_lookup_cmap_full(pdf_cmap *cmap, int cpt, int *out)
  392. {
  393. int i, k, n;
  394. int l = 0;
  395. int r = cmap->rlen - 1;
  396. int m;
  397. while (l <= r)
  398. {
  399. m = (l + r) >> 1;
  400. if (cpt < cmap->ranges[m].low)
  401. r = m - 1;
  402. else if (cpt > pdf_range_high(&cmap->ranges[m]))
  403. l = m + 1;
  404. else
  405. {
  406. k = cpt - cmap->ranges[m].low + cmap->ranges[m].offset;
  407. if (pdf_range_flags(&cmap->ranges[m]) == PDF_CMAP_TABLE)
  408. {
  409. out[0] = cmap->table[k];
  410. return 1;
  411. }
  412. else if (pdf_range_flags(&cmap->ranges[m]) == PDF_CMAP_MULTI)
  413. {
  414. n = cmap->ranges[m].offset;
  415. for (i = 0; i < cmap->table[n]; i++)
  416. out[i] = cmap->table[n + i + 1];
  417. return cmap->table[n];
  418. }
  419. else
  420. {
  421. out[0] = k;
  422. return 1;
  423. }
  424. }
  425. }
  426. if (cmap->usecmap)
  427. return pdf_lookup_cmap_full(cmap->usecmap, cpt, out);
  428. return 0;
  429. }
  430. /*
  431. * Use the codespace ranges to extract a codepoint from a
  432. * multi-byte encoded string.
  433. */
  434. int
  435. pdf_decode_cmap(pdf_cmap *cmap, unsigned char *buf, int *cpt)
  436. {
  437. int k, n, c;
  438. c = 0;
  439. for (n = 0; n < 4; n++)
  440. {
  441. c = (c << 8) | buf[n];
  442. for (k = 0; k < cmap->codespace_len; k++)
  443. {
  444. if (cmap->codespace[k].n == n + 1)
  445. {
  446. if (c >= cmap->codespace[k].low && c <= cmap->codespace[k].high)
  447. {
  448. *cpt = c;
  449. return n + 1;
  450. }
  451. }
  452. }
  453. }
  454. *cpt = 0;
  455. return 1;
  456. }