pdf_object.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. #include "fitz-internal.h"
  2. #include "mupdf-internal.h"
  3. typedef enum pdf_objkind_e
  4. {
  5. PDF_NULL = 0,
  6. PDF_BOOL = 'b',
  7. PDF_INT = 'i',
  8. PDF_REAL = 'f',
  9. PDF_STRING = 's',
  10. PDF_NAME = 'n',
  11. PDF_ARRAY = 'a',
  12. PDF_DICT = 'd',
  13. PDF_INDIRECT = 'r'
  14. } pdf_objkind;
  15. struct keyval
  16. {
  17. pdf_obj *k;
  18. pdf_obj *v;
  19. };
  20. struct pdf_obj_s
  21. {
  22. int refs;
  23. char kind;
  24. char marked;
  25. fz_context *ctx;
  26. union
  27. {
  28. int b;
  29. int i;
  30. float f;
  31. struct {
  32. unsigned short len;
  33. char buf[1];
  34. } s;
  35. char n[1];
  36. struct {
  37. int len;
  38. int cap;
  39. pdf_obj **items;
  40. } a;
  41. struct {
  42. char sorted;
  43. int len;
  44. int cap;
  45. struct keyval *items;
  46. } d;
  47. struct {
  48. int num;
  49. int gen;
  50. struct pdf_xref_s *xref;
  51. } r;
  52. } u;
  53. };
  54. pdf_obj *
  55. pdf_new_null(fz_context *ctx)
  56. {
  57. pdf_obj *obj;
  58. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(null)");
  59. obj->ctx = ctx;
  60. obj->refs = 1;
  61. obj->kind = PDF_NULL;
  62. obj->marked = 0;
  63. return obj;
  64. }
  65. pdf_obj *
  66. pdf_new_bool(fz_context *ctx, int b)
  67. {
  68. pdf_obj *obj;
  69. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(bool)");
  70. obj->ctx = ctx;
  71. obj->refs = 1;
  72. obj->kind = PDF_BOOL;
  73. obj->marked = 0;
  74. obj->u.b = b;
  75. return obj;
  76. }
  77. pdf_obj *
  78. pdf_new_int(fz_context *ctx, int i)
  79. {
  80. pdf_obj *obj;
  81. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(int)");
  82. obj->ctx = ctx;
  83. obj->refs = 1;
  84. obj->kind = PDF_INT;
  85. obj->marked = 0;
  86. obj->u.i = i;
  87. return obj;
  88. }
  89. pdf_obj *
  90. pdf_new_real(fz_context *ctx, float f)
  91. {
  92. pdf_obj *obj;
  93. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(real)");
  94. obj->ctx = ctx;
  95. obj->refs = 1;
  96. obj->kind = PDF_REAL;
  97. obj->marked = 0;
  98. obj->u.f = f;
  99. return obj;
  100. }
  101. pdf_obj *
  102. pdf_new_string(fz_context *ctx, const char *str, int len)
  103. {
  104. pdf_obj *obj;
  105. obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.s.buf) + len + 1), "pdf_obj(string)");
  106. obj->ctx = ctx;
  107. obj->refs = 1;
  108. obj->kind = PDF_STRING;
  109. obj->marked = 0;
  110. obj->u.s.len = len;
  111. memcpy(obj->u.s.buf, str, len);
  112. obj->u.s.buf[len] = '\0';
  113. return obj;
  114. }
  115. pdf_obj *
  116. pdf_new_name(fz_context *ctx, const char *str)
  117. {
  118. pdf_obj *obj;
  119. obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.n) + strlen(str) + 1), "pdf_obj(name)");
  120. obj->ctx = ctx;
  121. obj->refs = 1;
  122. obj->kind = PDF_NAME;
  123. obj->marked = 0;
  124. strcpy(obj->u.n, str);
  125. return obj;
  126. }
  127. pdf_obj *
  128. pdf_new_indirect(fz_context *ctx, int num, int gen, void *xref)
  129. {
  130. pdf_obj *obj;
  131. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(indirect)");
  132. obj->ctx = ctx;
  133. obj->refs = 1;
  134. obj->kind = PDF_INDIRECT;
  135. obj->marked = 0;
  136. obj->u.r.num = num;
  137. obj->u.r.gen = gen;
  138. obj->u.r.xref = xref;
  139. return obj;
  140. }
  141. pdf_obj *
  142. pdf_keep_obj(pdf_obj *obj)
  143. {
  144. if (obj)
  145. obj->refs ++;
  146. return obj;
  147. }
  148. int pdf_is_indirect(pdf_obj *obj)
  149. {
  150. return obj ? obj->kind == PDF_INDIRECT : 0;
  151. }
  152. #define RESOLVE(obj) \
  153. do { \
  154. if (obj && obj->kind == PDF_INDIRECT) \
  155. {\
  156. obj = pdf_resolve_indirect(obj); \
  157. } \
  158. } while (0)
  159. int pdf_is_null(pdf_obj *obj)
  160. {
  161. RESOLVE(obj);
  162. return obj ? obj->kind == PDF_NULL : 0;
  163. }
  164. int pdf_is_bool(pdf_obj *obj)
  165. {
  166. RESOLVE(obj);
  167. return obj ? obj->kind == PDF_BOOL : 0;
  168. }
  169. int pdf_is_int(pdf_obj *obj)
  170. {
  171. RESOLVE(obj);
  172. return obj ? obj->kind == PDF_INT : 0;
  173. }
  174. int pdf_is_real(pdf_obj *obj)
  175. {
  176. RESOLVE(obj);
  177. return obj ? obj->kind == PDF_REAL : 0;
  178. }
  179. int pdf_is_string(pdf_obj *obj)
  180. {
  181. RESOLVE(obj);
  182. return obj ? obj->kind == PDF_STRING : 0;
  183. }
  184. int pdf_is_name(pdf_obj *obj)
  185. {
  186. RESOLVE(obj);
  187. return obj ? obj->kind == PDF_NAME : 0;
  188. }
  189. int pdf_is_array(pdf_obj *obj)
  190. {
  191. RESOLVE(obj);
  192. return obj ? obj->kind == PDF_ARRAY : 0;
  193. }
  194. int pdf_is_dict(pdf_obj *obj)
  195. {
  196. RESOLVE(obj);
  197. return obj ? obj->kind == PDF_DICT : 0;
  198. }
  199. int pdf_to_bool(pdf_obj *obj)
  200. {
  201. RESOLVE(obj);
  202. if (!obj)
  203. return 0;
  204. return obj->kind == PDF_BOOL ? obj->u.b : 0;
  205. }
  206. int pdf_to_int(pdf_obj *obj)
  207. {
  208. RESOLVE(obj);
  209. if (!obj)
  210. return 0;
  211. if (obj->kind == PDF_INT)
  212. return obj->u.i;
  213. if (obj->kind == PDF_REAL)
  214. return (int)(obj->u.f + 0.5f); /* No roundf in MSVC */
  215. return 0;
  216. }
  217. float pdf_to_real(pdf_obj *obj)
  218. {
  219. RESOLVE(obj);
  220. if (!obj)
  221. return 0;
  222. if (obj->kind == PDF_REAL)
  223. return obj->u.f;
  224. if (obj->kind == PDF_INT)
  225. return obj->u.i;
  226. return 0;
  227. }
  228. char *pdf_to_name(pdf_obj *obj)
  229. {
  230. RESOLVE(obj);
  231. if (!obj || obj->kind != PDF_NAME)
  232. return "";
  233. return obj->u.n;
  234. }
  235. char *pdf_to_str_buf(pdf_obj *obj)
  236. {
  237. RESOLVE(obj);
  238. if (!obj || obj->kind != PDF_STRING)
  239. return "";
  240. return obj->u.s.buf;
  241. }
  242. int pdf_to_str_len(pdf_obj *obj)
  243. {
  244. RESOLVE(obj);
  245. if (!obj || obj->kind != PDF_STRING)
  246. return 0;
  247. return obj->u.s.len;
  248. }
  249. void pdf_set_int(pdf_obj *obj, int i)
  250. {
  251. if (!obj || obj->kind != PDF_INT)
  252. return;
  253. obj->u.i = i;
  254. }
  255. /* for use by pdf_crypt_obj_imp to decrypt AES string in place */
  256. void pdf_set_str_len(pdf_obj *obj, int newlen)
  257. {
  258. RESOLVE(obj);
  259. if (!obj || obj->kind != PDF_STRING)
  260. return; /* This should never happen */
  261. if (newlen > obj->u.s.len)
  262. return; /* This should never happen */
  263. obj->u.s.len = newlen;
  264. }
  265. pdf_obj *pdf_to_dict(pdf_obj *obj)
  266. {
  267. RESOLVE(obj);
  268. return (obj && obj->kind == PDF_DICT ? obj : NULL);
  269. }
  270. int pdf_to_num(pdf_obj *obj)
  271. {
  272. if (!obj || obj->kind != PDF_INDIRECT)
  273. return 0;
  274. return obj->u.r.num;
  275. }
  276. int pdf_to_gen(pdf_obj *obj)
  277. {
  278. if (!obj || obj->kind != PDF_INDIRECT)
  279. return 0;
  280. return obj->u.r.gen;
  281. }
  282. void *pdf_get_indirect_document(pdf_obj *obj)
  283. {
  284. if (!obj || obj->kind != PDF_INDIRECT)
  285. return NULL;
  286. return obj->u.r.xref;
  287. }
  288. int
  289. pdf_objcmp(pdf_obj *a, pdf_obj *b)
  290. {
  291. int i;
  292. if (a == b)
  293. return 0;
  294. if (!a || !b)
  295. return 1;
  296. if (a->kind != b->kind)
  297. return 1;
  298. switch (a->kind)
  299. {
  300. case PDF_NULL:
  301. return 0;
  302. case PDF_BOOL:
  303. return a->u.b - b->u.b;
  304. case PDF_INT:
  305. return a->u.i - b->u.i;
  306. case PDF_REAL:
  307. if (a->u.f < b->u.f)
  308. return -1;
  309. if (a->u.f > b->u.f)
  310. return 1;
  311. return 0;
  312. case PDF_STRING:
  313. if (a->u.s.len < b->u.s.len)
  314. {
  315. if (memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len) <= 0)
  316. return -1;
  317. return 1;
  318. }
  319. if (a->u.s.len > b->u.s.len)
  320. {
  321. if (memcmp(a->u.s.buf, b->u.s.buf, b->u.s.len) >= 0)
  322. return 1;
  323. return -1;
  324. }
  325. return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len);
  326. case PDF_NAME:
  327. return strcmp(a->u.n, b->u.n);
  328. case PDF_INDIRECT:
  329. if (a->u.r.num == b->u.r.num)
  330. return a->u.r.gen - b->u.r.gen;
  331. return a->u.r.num - b->u.r.num;
  332. case PDF_ARRAY:
  333. if (a->u.a.len != b->u.a.len)
  334. return a->u.a.len - b->u.a.len;
  335. for (i = 0; i < a->u.a.len; i++)
  336. if (pdf_objcmp(a->u.a.items[i], b->u.a.items[i]))
  337. return 1;
  338. return 0;
  339. case PDF_DICT:
  340. if (a->u.d.len != b->u.d.len)
  341. return a->u.d.len - b->u.d.len;
  342. for (i = 0; i < a->u.d.len; i++)
  343. {
  344. if (pdf_objcmp(a->u.d.items[i].k, b->u.d.items[i].k))
  345. return 1;
  346. if (pdf_objcmp(a->u.d.items[i].v, b->u.d.items[i].v))
  347. return 1;
  348. }
  349. return 0;
  350. }
  351. return 1;
  352. }
  353. static char *
  354. pdf_objkindstr(pdf_obj *obj)
  355. {
  356. if (!obj)
  357. return "<NULL>";
  358. switch (obj->kind)
  359. {
  360. case PDF_NULL: return "null";
  361. case PDF_BOOL: return "boolean";
  362. case PDF_INT: return "integer";
  363. case PDF_REAL: return "real";
  364. case PDF_STRING: return "string";
  365. case PDF_NAME: return "name";
  366. case PDF_ARRAY: return "array";
  367. case PDF_DICT: return "dictionary";
  368. case PDF_INDIRECT: return "reference";
  369. }
  370. return "<unknown>";
  371. }
  372. pdf_obj *
  373. pdf_new_array(fz_context *ctx, int initialcap)
  374. {
  375. pdf_obj *obj;
  376. int i;
  377. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(array)");
  378. obj->ctx = ctx;
  379. obj->refs = 1;
  380. obj->kind = PDF_ARRAY;
  381. obj->marked = 0;
  382. obj->u.a.len = 0;
  383. obj->u.a.cap = initialcap > 1 ? initialcap : 6;
  384. fz_try(ctx)
  385. {
  386. obj->u.a.items = Memento_label(fz_malloc_array(ctx, obj->u.a.cap, sizeof(pdf_obj*)), "pdf_obj(array items)");
  387. }
  388. fz_catch(ctx)
  389. {
  390. fz_free(ctx, obj);
  391. fz_rethrow(ctx);
  392. }
  393. for (i = 0; i < obj->u.a.cap; i++)
  394. obj->u.a.items[i] = NULL;
  395. return obj;
  396. }
  397. static void
  398. pdf_array_grow(pdf_obj *obj)
  399. {
  400. int i;
  401. int new_cap = (obj->u.a.cap * 3) / 2;
  402. obj->u.a.items = fz_resize_array(obj->ctx, obj->u.a.items, new_cap, sizeof(pdf_obj*));
  403. obj->u.a.cap = new_cap;
  404. for (i = obj->u.a.len ; i < obj->u.a.cap; i++)
  405. obj->u.a.items[i] = NULL;
  406. }
  407. pdf_obj *
  408. pdf_copy_array(fz_context *ctx, pdf_obj *obj)
  409. {
  410. pdf_obj *arr;
  411. int i;
  412. int n;
  413. RESOLVE(obj);
  414. if (!obj)
  415. return NULL; /* Can't warn :( */
  416. if (obj->kind != PDF_ARRAY)
  417. fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
  418. arr = pdf_new_array(ctx, pdf_array_len(obj));
  419. n = pdf_array_len(obj);
  420. for (i = 0; i < n; i++)
  421. pdf_array_push(arr, pdf_array_get(obj, i));
  422. return arr;
  423. }
  424. int
  425. pdf_array_len(pdf_obj *obj)
  426. {
  427. RESOLVE(obj);
  428. if (!obj || obj->kind != PDF_ARRAY)
  429. return 0;
  430. return obj->u.a.len;
  431. }
  432. pdf_obj *
  433. pdf_array_get(pdf_obj *obj, int i)
  434. {
  435. RESOLVE(obj);
  436. if (!obj || obj->kind != PDF_ARRAY)
  437. return NULL;
  438. if (i < 0 || i >= obj->u.a.len)
  439. return NULL;
  440. return obj->u.a.items[i];
  441. }
  442. void
  443. pdf_array_put(pdf_obj *obj, int i, pdf_obj *item)
  444. {
  445. RESOLVE(obj);
  446. if (!obj)
  447. return; /* Can't warn :( */
  448. if (obj->kind != PDF_ARRAY)
  449. fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
  450. else if (i < 0)
  451. fz_warn(obj->ctx, "assert: index %d < 0", i);
  452. else if (i >= obj->u.a.len)
  453. fz_warn(obj->ctx, "assert: index %d > length %d", i, obj->u.a.len);
  454. else
  455. {
  456. pdf_drop_obj(obj->u.a.items[i]);
  457. obj->u.a.items[i] = pdf_keep_obj(item);
  458. }
  459. }
  460. void
  461. pdf_array_push(pdf_obj *obj, pdf_obj *item)
  462. {
  463. RESOLVE(obj);
  464. if (!obj)
  465. return; /* Can't warn :( */
  466. if (obj->kind != PDF_ARRAY)
  467. fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
  468. else
  469. {
  470. if (obj->u.a.len + 1 > obj->u.a.cap)
  471. pdf_array_grow(obj);
  472. obj->u.a.items[obj->u.a.len] = pdf_keep_obj(item);
  473. obj->u.a.len++;
  474. }
  475. }
  476. void
  477. pdf_array_push_drop(pdf_obj *obj, pdf_obj *item)
  478. {
  479. fz_context *ctx = obj->ctx;
  480. fz_try(ctx)
  481. {
  482. pdf_array_push(obj, item);
  483. }
  484. fz_always(ctx)
  485. {
  486. pdf_drop_obj(item);
  487. }
  488. fz_catch(ctx)
  489. {
  490. fz_rethrow(ctx);
  491. }
  492. }
  493. void
  494. pdf_array_insert(pdf_obj *obj, pdf_obj *item)
  495. {
  496. RESOLVE(obj);
  497. if (!obj)
  498. return; /* Can't warn :( */
  499. if (obj->kind != PDF_ARRAY)
  500. fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
  501. else
  502. {
  503. if (obj->u.a.len + 1 > obj->u.a.cap)
  504. pdf_array_grow(obj);
  505. memmove(obj->u.a.items + 1, obj->u.a.items, obj->u.a.len * sizeof(pdf_obj*));
  506. obj->u.a.items[0] = pdf_keep_obj(item);
  507. obj->u.a.len++;
  508. }
  509. }
  510. int
  511. pdf_array_contains(pdf_obj *arr, pdf_obj *obj)
  512. {
  513. int i, len;
  514. len = pdf_array_len(arr);
  515. for (i = 0; i < len; i++)
  516. if (!pdf_objcmp(pdf_array_get(arr, i), obj))
  517. return 1;
  518. return 0;
  519. }
  520. pdf_obj *pdf_new_rect(fz_context *ctx, const fz_rect *rect)
  521. {
  522. pdf_obj *arr = NULL;
  523. pdf_obj *item = NULL;
  524. fz_var(arr);
  525. fz_var(item);
  526. fz_try(ctx)
  527. {
  528. arr = pdf_new_array(ctx, 4);
  529. item = pdf_new_real(ctx, rect->x0);
  530. pdf_array_push(arr, item);
  531. pdf_drop_obj(item);
  532. item = NULL;
  533. item = pdf_new_real(ctx, rect->y0);
  534. pdf_array_push(arr, item);
  535. pdf_drop_obj(item);
  536. item = NULL;
  537. item = pdf_new_real(ctx, rect->x1);
  538. pdf_array_push(arr, item);
  539. pdf_drop_obj(item);
  540. item = NULL;
  541. item = pdf_new_real(ctx, rect->y1);
  542. pdf_array_push(arr, item);
  543. pdf_drop_obj(item);
  544. item = NULL;
  545. }
  546. fz_catch(ctx)
  547. {
  548. pdf_drop_obj(item);
  549. pdf_drop_obj(arr);
  550. fz_rethrow(ctx);
  551. }
  552. return arr;
  553. }
  554. pdf_obj *pdf_new_matrix(fz_context *ctx, const fz_matrix *mtx)
  555. {
  556. pdf_obj *arr = NULL;
  557. pdf_obj *item = NULL;
  558. fz_var(arr);
  559. fz_var(item);
  560. fz_try(ctx)
  561. {
  562. arr = pdf_new_array(ctx, 6);
  563. item = pdf_new_real(ctx, mtx->a);
  564. pdf_array_push(arr, item);
  565. pdf_drop_obj(item);
  566. item = NULL;
  567. item = pdf_new_real(ctx, mtx->b);
  568. pdf_array_push(arr, item);
  569. pdf_drop_obj(item);
  570. item = NULL;
  571. item = pdf_new_real(ctx, mtx->c);
  572. pdf_array_push(arr, item);
  573. pdf_drop_obj(item);
  574. item = NULL;
  575. item = pdf_new_real(ctx, mtx->d);
  576. pdf_array_push(arr, item);
  577. pdf_drop_obj(item);
  578. item = NULL;
  579. item = pdf_new_real(ctx, mtx->e);
  580. pdf_array_push(arr, item);
  581. pdf_drop_obj(item);
  582. item = NULL;
  583. item = pdf_new_real(ctx, mtx->f);
  584. pdf_array_push(arr, item);
  585. pdf_drop_obj(item);
  586. item = NULL;
  587. }
  588. fz_catch(ctx)
  589. {
  590. pdf_drop_obj(item);
  591. pdf_drop_obj(arr);
  592. fz_rethrow(ctx);
  593. }
  594. return arr;
  595. }
  596. /* dicts may only have names as keys! */
  597. static int keyvalcmp(const void *ap, const void *bp)
  598. {
  599. const struct keyval *a = ap;
  600. const struct keyval *b = bp;
  601. return strcmp(pdf_to_name(a->k), pdf_to_name(b->k));
  602. }
  603. pdf_obj *
  604. pdf_new_dict(fz_context *ctx, int initialcap)
  605. {
  606. pdf_obj *obj;
  607. int i;
  608. obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(dict)");
  609. obj->ctx = ctx;
  610. obj->refs = 1;
  611. obj->kind = PDF_DICT;
  612. obj->marked = 0;
  613. obj->u.d.sorted = 0;
  614. obj->u.d.len = 0;
  615. obj->u.d.cap = initialcap > 1 ? initialcap : 10;
  616. fz_try(ctx)
  617. {
  618. obj->u.d.items = Memento_label(fz_malloc_array(ctx, obj->u.d.cap, sizeof(struct keyval)), "pdf_obj(dict items)");
  619. }
  620. fz_catch(ctx)
  621. {
  622. fz_free(ctx, obj);
  623. fz_rethrow(ctx);
  624. }
  625. for (i = 0; i < obj->u.d.cap; i++)
  626. {
  627. obj->u.d.items[i].k = NULL;
  628. obj->u.d.items[i].v = NULL;
  629. }
  630. return obj;
  631. }
  632. static void
  633. pdf_dict_grow(pdf_obj *obj)
  634. {
  635. int i;
  636. int new_cap = (obj->u.d.cap * 3) / 2;
  637. obj->u.d.items = fz_resize_array(obj->ctx, obj->u.d.items, new_cap, sizeof(struct keyval));
  638. obj->u.d.cap = new_cap;
  639. for (i = obj->u.d.len; i < obj->u.d.cap; i++)
  640. {
  641. obj->u.d.items[i].k = NULL;
  642. obj->u.d.items[i].v = NULL;
  643. }
  644. }
  645. pdf_obj *
  646. pdf_copy_dict(fz_context *ctx, pdf_obj *obj)
  647. {
  648. pdf_obj *dict;
  649. int i, n;
  650. RESOLVE(obj);
  651. if (!obj)
  652. return NULL; /* Can't warn :( */
  653. if (obj->kind != PDF_DICT)
  654. fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
  655. n = pdf_dict_len(obj);
  656. dict = pdf_new_dict(ctx, n);
  657. for (i = 0; i < n; i++)
  658. pdf_dict_put(dict, pdf_dict_get_key(obj, i), pdf_dict_get_val(obj, i));
  659. return dict;
  660. }
  661. int
  662. pdf_dict_len(pdf_obj *obj)
  663. {
  664. RESOLVE(obj);
  665. if (!obj || obj->kind != PDF_DICT)
  666. return 0;
  667. return obj->u.d.len;
  668. }
  669. pdf_obj *
  670. pdf_dict_get_key(pdf_obj *obj, int i)
  671. {
  672. RESOLVE(obj);
  673. if (!obj || obj->kind != PDF_DICT)
  674. return NULL;
  675. if (i < 0 || i >= obj->u.d.len)
  676. return NULL;
  677. return obj->u.d.items[i].k;
  678. }
  679. pdf_obj *
  680. pdf_dict_get_val(pdf_obj *obj, int i)
  681. {
  682. RESOLVE(obj);
  683. if (!obj || obj->kind != PDF_DICT)
  684. return NULL;
  685. if (i < 0 || i >= obj->u.d.len)
  686. return NULL;
  687. return obj->u.d.items[i].v;
  688. }
  689. static int
  690. pdf_dict_finds(pdf_obj *obj, const char *key, int *location)
  691. {
  692. if (obj->u.d.sorted && obj->u.d.len > 0)
  693. {
  694. int l = 0;
  695. int r = obj->u.d.len - 1;
  696. if (strcmp(pdf_to_name(obj->u.d.items[r].k), key) < 0)
  697. {
  698. if (location)
  699. *location = r + 1;
  700. return -1;
  701. }
  702. while (l <= r)
  703. {
  704. int m = (l + r) >> 1;
  705. int c = -strcmp(pdf_to_name(obj->u.d.items[m].k), key);
  706. if (c < 0)
  707. r = m - 1;
  708. else if (c > 0)
  709. l = m + 1;
  710. else
  711. return m;
  712. if (location)
  713. *location = l;
  714. }
  715. }
  716. else
  717. {
  718. int i;
  719. for (i = 0; i < obj->u.d.len; i++)
  720. if (strcmp(pdf_to_name(obj->u.d.items[i].k), key) == 0)
  721. return i;
  722. if (location)
  723. *location = obj->u.d.len;
  724. }
  725. return -1;
  726. }
  727. pdf_obj *
  728. pdf_dict_gets(pdf_obj *obj, const char *key)
  729. {
  730. int i;
  731. RESOLVE(obj);
  732. if (!obj || obj->kind != PDF_DICT)
  733. return NULL;
  734. i = pdf_dict_finds(obj, key, NULL);
  735. if (i >= 0)
  736. return obj->u.d.items[i].v;
  737. return NULL;
  738. }
  739. pdf_obj *
  740. pdf_dict_getp(pdf_obj *obj, const char *keys)
  741. {
  742. char buf[256];
  743. char *k, *e;
  744. if (strlen(keys)+1 > 256)
  745. fz_throw(obj->ctx, "buffer overflow in pdf_dict_getp");
  746. strcpy(buf, keys);
  747. e = buf;
  748. while (*e && obj)
  749. {
  750. k = e;
  751. while (*e != '/' && *e != '\0')
  752. e++;
  753. if (*e == '/')
  754. {
  755. *e = '\0';
  756. e++;
  757. }
  758. obj = pdf_dict_gets(obj, k);
  759. }
  760. return obj;
  761. }
  762. pdf_obj *
  763. pdf_dict_get(pdf_obj *obj, pdf_obj *key)
  764. {
  765. if (!key || key->kind != PDF_NAME)
  766. return NULL;
  767. return pdf_dict_gets(obj, pdf_to_name(key));
  768. }
  769. pdf_obj *
  770. pdf_dict_getsa(pdf_obj *obj, const char *key, const char *abbrev)
  771. {
  772. pdf_obj *v;
  773. v = pdf_dict_gets(obj, key);
  774. if (v)
  775. return v;
  776. return pdf_dict_gets(obj, abbrev);
  777. }
  778. void
  779. pdf_dict_put(pdf_obj *obj, pdf_obj *key, pdf_obj *val)
  780. {
  781. int location;
  782. char *s;
  783. int i;
  784. RESOLVE(obj);
  785. if (!obj)
  786. return; /* Can't warn :( */
  787. if (obj->kind != PDF_DICT)
  788. {
  789. fz_warn(obj->ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
  790. return;
  791. }
  792. RESOLVE(key);
  793. if (!key || key->kind != PDF_NAME)
  794. {
  795. fz_warn(obj->ctx, "assert: key is not a name (%s)", pdf_objkindstr(obj));
  796. return;
  797. }
  798. else
  799. s = pdf_to_name(key);
  800. if (!val)
  801. {
  802. fz_warn(obj->ctx, "assert: val does not exist for key (%s)", s);
  803. return;
  804. }
  805. if (obj->u.d.len > 100 && !obj->u.d.sorted)
  806. pdf_sort_dict(obj);
  807. i = pdf_dict_finds(obj, s, &location);
  808. if (i >= 0 && i < obj->u.d.len)
  809. {
  810. if (obj->u.d.items[i].v != val)
  811. {
  812. pdf_drop_obj(obj->u.d.items[i].v);
  813. obj->u.d.items[i].v = pdf_keep_obj(val);
  814. }
  815. }
  816. else
  817. {
  818. if (obj->u.d.len + 1 > obj->u.d.cap)
  819. pdf_dict_grow(obj);
  820. i = location;
  821. if (obj->u.d.sorted && obj->u.d.len > 0)
  822. memmove(&obj->u.d.items[i + 1],
  823. &obj->u.d.items[i],
  824. (obj->u.d.len - i) * sizeof(struct keyval));
  825. obj->u.d.items[i].k = pdf_keep_obj(key);
  826. obj->u.d.items[i].v = pdf_keep_obj(val);
  827. obj->u.d.len ++;
  828. }
  829. }
  830. void
  831. pdf_dict_puts(pdf_obj *obj, const char *key, pdf_obj *val)
  832. {
  833. fz_context *ctx = obj->ctx;
  834. pdf_obj *keyobj = pdf_new_name(ctx, key);
  835. fz_try(ctx)
  836. {
  837. pdf_dict_put(obj, keyobj, val);
  838. }
  839. fz_always(ctx)
  840. {
  841. pdf_drop_obj(keyobj);
  842. }
  843. fz_catch(ctx)
  844. {
  845. fz_rethrow(ctx);
  846. }
  847. }
  848. void
  849. pdf_dict_puts_drop(pdf_obj *obj, const char *key, pdf_obj *val)
  850. {
  851. fz_context *ctx = obj->ctx;
  852. pdf_obj *keyobj = NULL;
  853. fz_var(keyobj);
  854. fz_try(ctx)
  855. {
  856. keyobj = pdf_new_name(ctx, key);
  857. pdf_dict_put(obj, keyobj, val);
  858. }
  859. fz_always(ctx)
  860. {
  861. pdf_drop_obj(keyobj);
  862. pdf_drop_obj(val);
  863. }
  864. fz_catch(ctx)
  865. {
  866. fz_rethrow(ctx);
  867. }
  868. }
  869. void
  870. pdf_dict_putp(pdf_obj *obj, const char *keys, pdf_obj *val)
  871. {
  872. fz_context *ctx = obj->ctx;
  873. char buf[256];
  874. char *k, *e;
  875. pdf_obj *cobj = NULL;
  876. if (strlen(keys)+1 > 256)
  877. fz_throw(obj->ctx, "buffer overflow in pdf_dict_getp");
  878. strcpy(buf, keys);
  879. e = buf;
  880. while (*e)
  881. {
  882. k = e;
  883. while (*e != '/' && *e != '\0')
  884. e++;
  885. if (*e == '/')
  886. {
  887. *e = '\0';
  888. e++;
  889. }
  890. if (*e)
  891. {
  892. /* Not the last key in the key path. Create subdict if not already there. */
  893. cobj = pdf_dict_gets(obj, k);
  894. if (cobj == NULL)
  895. {
  896. cobj = pdf_new_dict(ctx, 1);
  897. fz_try(ctx)
  898. {
  899. pdf_dict_puts(obj, k, cobj);
  900. }
  901. fz_always(ctx)
  902. {
  903. pdf_drop_obj(cobj);
  904. }
  905. fz_catch(ctx)
  906. {
  907. fz_rethrow(ctx);
  908. }
  909. }
  910. /* Move to subdict */
  911. obj = cobj;
  912. }
  913. else
  914. {
  915. /* Last key. Use it to store the value */
  916. /* Use val = NULL to request delete */
  917. if (val)
  918. pdf_dict_puts(obj, k, val);
  919. else
  920. pdf_dict_dels(obj, k);
  921. }
  922. }
  923. }
  924. void
  925. pdf_dict_putp_drop(pdf_obj *obj, const char *keys, pdf_obj *val)
  926. {
  927. fz_context *ctx = obj->ctx;
  928. fz_try(ctx)
  929. {
  930. pdf_dict_putp(obj, keys, val);
  931. }
  932. fz_always(ctx)
  933. {
  934. pdf_drop_obj(val);
  935. }
  936. fz_catch(ctx)
  937. {
  938. fz_rethrow(ctx);
  939. }
  940. }
  941. void
  942. pdf_dict_dels(pdf_obj *obj, const char *key)
  943. {
  944. RESOLVE(obj);
  945. if (!obj)
  946. return; /* Can't warn :( */
  947. if (obj->kind != PDF_DICT)
  948. fz_warn(obj->ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
  949. else
  950. {
  951. int i = pdf_dict_finds(obj, key, NULL);
  952. if (i >= 0)
  953. {
  954. pdf_drop_obj(obj->u.d.items[i].k);
  955. pdf_drop_obj(obj->u.d.items[i].v);
  956. obj->u.d.sorted = 0;
  957. obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1];
  958. obj->u.d.len --;
  959. }
  960. }
  961. }
  962. void
  963. pdf_dict_del(pdf_obj *obj, pdf_obj *key)
  964. {
  965. RESOLVE(key);
  966. if (!key || key->kind != PDF_NAME)
  967. fz_warn(obj->ctx, "assert: key is not a name (%s)", pdf_objkindstr(obj));
  968. else
  969. pdf_dict_dels(obj, key->u.n);
  970. }
  971. void
  972. pdf_sort_dict(pdf_obj *obj)
  973. {
  974. RESOLVE(obj);
  975. if (!obj || obj->kind != PDF_DICT)
  976. return;
  977. if (!obj->u.d.sorted)
  978. {
  979. qsort(obj->u.d.items, obj->u.d.len, sizeof(struct keyval), keyvalcmp);
  980. obj->u.d.sorted = 1;
  981. }
  982. }
  983. int
  984. pdf_obj_marked(pdf_obj *obj)
  985. {
  986. RESOLVE(obj);
  987. if (!obj)
  988. return 0;
  989. return obj->marked;
  990. }
  991. int
  992. pdf_obj_mark(pdf_obj *obj)
  993. {
  994. int marked;
  995. RESOLVE(obj);
  996. if (!obj)
  997. return 0;
  998. marked = obj->marked;
  999. obj->marked = 1;
  1000. return marked;
  1001. }
  1002. void
  1003. pdf_obj_unmark(pdf_obj *obj)
  1004. {
  1005. RESOLVE(obj);
  1006. if (!obj)
  1007. return;
  1008. obj->marked = 0;
  1009. }
  1010. static void
  1011. pdf_free_array(pdf_obj *obj)
  1012. {
  1013. int i;
  1014. for (i = 0; i < obj->u.a.len; i++)
  1015. pdf_drop_obj(obj->u.a.items[i]);
  1016. fz_free(obj->ctx, obj->u.a.items);
  1017. fz_free(obj->ctx, obj);
  1018. }
  1019. static void
  1020. pdf_free_dict(pdf_obj *obj)
  1021. {
  1022. int i;
  1023. for (i = 0; i < obj->u.d.len; i++) {
  1024. pdf_drop_obj(obj->u.d.items[i].k);
  1025. pdf_drop_obj(obj->u.d.items[i].v);
  1026. }
  1027. fz_free(obj->ctx, obj->u.d.items);
  1028. fz_free(obj->ctx, obj);
  1029. }
  1030. void
  1031. pdf_drop_obj(pdf_obj *obj)
  1032. {
  1033. if (!obj)
  1034. return;
  1035. if (--obj->refs)
  1036. return;
  1037. if (obj->kind == PDF_ARRAY)
  1038. pdf_free_array(obj);
  1039. else if (obj->kind == PDF_DICT)
  1040. pdf_free_dict(obj);
  1041. else
  1042. fz_free(obj->ctx, obj);
  1043. }
  1044. pdf_obj *pdf_new_obj_from_str(fz_context *ctx, const char *src)
  1045. {
  1046. pdf_obj *result;
  1047. pdf_lexbuf lexbuf;
  1048. fz_stream *stream = fz_open_memory(ctx, (unsigned char *)src, strlen(src));
  1049. pdf_lexbuf_init(ctx, &lexbuf, PDF_LEXBUF_SMALL);
  1050. fz_try(ctx)
  1051. {
  1052. result = pdf_parse_stm_obj(NULL, stream, &lexbuf);
  1053. }
  1054. fz_always(ctx)
  1055. {
  1056. pdf_lexbuf_fin(&lexbuf);
  1057. fz_close(stream);
  1058. }
  1059. fz_catch(ctx)
  1060. {
  1061. return NULL;
  1062. }
  1063. return result;
  1064. }
  1065. /* Pretty printing objects */
  1066. struct fmt
  1067. {
  1068. char *buf;
  1069. int cap;
  1070. int len;
  1071. int indent;
  1072. int tight;
  1073. int col;
  1074. int sep;
  1075. int last;
  1076. };
  1077. static void fmt_obj(struct fmt *fmt, pdf_obj *obj);
  1078. static inline int iswhite(int ch)
  1079. {
  1080. return
  1081. ch == '\000' ||
  1082. ch == '\011' ||
  1083. ch == '\012' ||
  1084. ch == '\014' ||
  1085. ch == '\015' ||
  1086. ch == '\040';
  1087. }
  1088. static inline int isdelim(int ch)
  1089. {
  1090. return
  1091. ch == '(' || ch == ')' ||
  1092. ch == '<' || ch == '>' ||
  1093. ch == '[' || ch == ']' ||
  1094. ch == '{' || ch == '}' ||
  1095. ch == '/' ||
  1096. ch == '%';
  1097. }
  1098. static inline void fmt_putc(struct fmt *fmt, int c)
  1099. {
  1100. if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) {
  1101. fmt->sep = 0;
  1102. fmt_putc(fmt, ' ');
  1103. }
  1104. fmt->sep = 0;
  1105. if (fmt->buf && fmt->len < fmt->cap)
  1106. fmt->buf[fmt->len] = c;
  1107. if (c == '\n')
  1108. fmt->col = 0;
  1109. else
  1110. fmt->col ++;
  1111. fmt->len ++;
  1112. fmt->last = c;
  1113. }
  1114. static inline void fmt_indent(struct fmt *fmt)
  1115. {
  1116. int i = fmt->indent;
  1117. while (i--) {
  1118. fmt_putc(fmt, ' ');
  1119. fmt_putc(fmt, ' ');
  1120. }
  1121. }
  1122. static inline void fmt_puts(struct fmt *fmt, char *s)
  1123. {
  1124. while (*s)
  1125. fmt_putc(fmt, *s++);
  1126. }
  1127. static inline void fmt_sep(struct fmt *fmt)
  1128. {
  1129. fmt->sep = 1;
  1130. }
  1131. static void fmt_str(struct fmt *fmt, pdf_obj *obj)
  1132. {
  1133. char *s = pdf_to_str_buf(obj);
  1134. int n = pdf_to_str_len(obj);
  1135. int i, c;
  1136. fmt_putc(fmt, '(');
  1137. for (i = 0; i < n; i++)
  1138. {
  1139. c = (unsigned char)s[i];
  1140. if (c == '\n')
  1141. fmt_puts(fmt, "\\n");
  1142. else if (c == '\r')
  1143. fmt_puts(fmt, "\\r");
  1144. else if (c == '\t')
  1145. fmt_puts(fmt, "\\t");
  1146. else if (c == '\b')
  1147. fmt_puts(fmt, "\\b");
  1148. else if (c == '\f')
  1149. fmt_puts(fmt, "\\f");
  1150. else if (c == '(')
  1151. fmt_puts(fmt, "\\(");
  1152. else if (c == ')')
  1153. fmt_puts(fmt, "\\)");
  1154. else if (c == '\\')
  1155. fmt_puts(fmt, "\\\\");
  1156. else if (c < 32 || c >= 127) {
  1157. char buf[16];
  1158. fmt_putc(fmt, '\\');
  1159. sprintf(buf, "%03o", c);
  1160. fmt_puts(fmt, buf);
  1161. }
  1162. else
  1163. fmt_putc(fmt, c);
  1164. }
  1165. fmt_putc(fmt, ')');
  1166. }
  1167. static void fmt_hex(struct fmt *fmt, pdf_obj *obj)
  1168. {
  1169. char *s = pdf_to_str_buf(obj);
  1170. int n = pdf_to_str_len(obj);
  1171. int i, b, c;
  1172. fmt_putc(fmt, '<');
  1173. for (i = 0; i < n; i++) {
  1174. b = (unsigned char) s[i];
  1175. c = (b >> 4) & 0x0f;
  1176. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  1177. c = (b) & 0x0f;
  1178. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  1179. }
  1180. fmt_putc(fmt, '>');
  1181. }
  1182. static void fmt_name(struct fmt *fmt, pdf_obj *obj)
  1183. {
  1184. unsigned char *s = (unsigned char *) pdf_to_name(obj);
  1185. int i, c;
  1186. fmt_putc(fmt, '/');
  1187. for (i = 0; s[i]; i++)
  1188. {
  1189. if (isdelim(s[i]) || iswhite(s[i]) ||
  1190. s[i] == '#' || s[i] < 32 || s[i] >= 127)
  1191. {
  1192. fmt_putc(fmt, '#');
  1193. c = (s[i] >> 4) & 0xf;
  1194. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  1195. c = s[i] & 0xf;
  1196. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  1197. }
  1198. else
  1199. {
  1200. fmt_putc(fmt, s[i]);
  1201. }
  1202. }
  1203. }
  1204. static void fmt_array(struct fmt *fmt, pdf_obj *obj)
  1205. {
  1206. int i, n;
  1207. n = pdf_array_len(obj);
  1208. if (fmt->tight) {
  1209. fmt_putc(fmt, '[');
  1210. for (i = 0; i < n; i++) {
  1211. fmt_obj(fmt, pdf_array_get(obj, i));
  1212. fmt_sep(fmt);
  1213. }
  1214. fmt_putc(fmt, ']');
  1215. }
  1216. else {
  1217. fmt_puts(fmt, "[ ");
  1218. for (i = 0; i < n; i++) {
  1219. if (fmt->col > 60) {
  1220. fmt_putc(fmt, '\n');
  1221. fmt_indent(fmt);
  1222. }
  1223. fmt_obj(fmt, pdf_array_get(obj, i));
  1224. fmt_putc(fmt, ' ');
  1225. }
  1226. fmt_putc(fmt, ']');
  1227. fmt_sep(fmt);
  1228. }
  1229. }
  1230. static void fmt_dict(struct fmt *fmt, pdf_obj *obj)
  1231. {
  1232. int i, n;
  1233. pdf_obj *key, *val;
  1234. n = pdf_dict_len(obj);
  1235. if (fmt->tight) {
  1236. fmt_puts(fmt, "<<");
  1237. for (i = 0; i < n; i++) {
  1238. fmt_obj(fmt, pdf_dict_get_key(obj, i));
  1239. fmt_sep(fmt);
  1240. fmt_obj(fmt, pdf_dict_get_val(obj, i));
  1241. fmt_sep(fmt);
  1242. }
  1243. fmt_puts(fmt, ">>");
  1244. }
  1245. else {
  1246. fmt_puts(fmt, "<<\n");
  1247. fmt->indent ++;
  1248. for (i = 0; i < n; i++) {
  1249. key = pdf_dict_get_key(obj, i);
  1250. val = pdf_dict_get_val(obj, i);
  1251. fmt_indent(fmt);
  1252. fmt_obj(fmt, key);
  1253. fmt_putc(fmt, ' ');
  1254. if (!pdf_is_indirect(val) && pdf_is_array(val))
  1255. fmt->indent ++;
  1256. fmt_obj(fmt, val);
  1257. fmt_putc(fmt, '\n');
  1258. if (!pdf_is_indirect(val) && pdf_is_array(val))
  1259. fmt->indent --;
  1260. }
  1261. fmt->indent --;
  1262. fmt_indent(fmt);
  1263. fmt_puts(fmt, ">>");
  1264. }
  1265. }
  1266. static void fmt_obj(struct fmt *fmt, pdf_obj *obj)
  1267. {
  1268. char buf[256];
  1269. if (!obj)
  1270. fmt_puts(fmt, "<NULL>");
  1271. else if (pdf_is_indirect(obj))
  1272. {
  1273. sprintf(buf, "%d %d R", pdf_to_num(obj), pdf_to_gen(obj));
  1274. fmt_puts(fmt, buf);
  1275. }
  1276. else if (pdf_is_null(obj))
  1277. fmt_puts(fmt, "null");
  1278. else if (pdf_is_bool(obj))
  1279. fmt_puts(fmt, pdf_to_bool(obj) ? "true" : "false");
  1280. else if (pdf_is_int(obj))
  1281. {
  1282. sprintf(buf, "%d", pdf_to_int(obj));
  1283. fmt_puts(fmt, buf);
  1284. }
  1285. else if (pdf_is_real(obj))
  1286. {
  1287. sprintf(buf, "%1.9g", pdf_to_real(obj));
  1288. if (strchr(buf, 'e')) /* bad news! */
  1289. sprintf(buf, fabsf(pdf_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", pdf_to_real(obj));
  1290. fmt_puts(fmt, buf);
  1291. }
  1292. else if (pdf_is_string(obj))
  1293. {
  1294. char *str = pdf_to_str_buf(obj);
  1295. int len = pdf_to_str_len(obj);
  1296. int added = 0;
  1297. int i, c;
  1298. for (i = 0; i < len; i++) {
  1299. c = (unsigned char)str[i];
  1300. if (strchr("()\\\n\r\t\b\f", c))
  1301. added ++;
  1302. else if (c < 32 || c >= 127)
  1303. added += 3;
  1304. }
  1305. if (added < len)
  1306. fmt_str(fmt, obj);
  1307. else
  1308. fmt_hex(fmt, obj);
  1309. }
  1310. else if (pdf_is_name(obj))
  1311. fmt_name(fmt, obj);
  1312. else if (pdf_is_array(obj))
  1313. fmt_array(fmt, obj);
  1314. else if (pdf_is_dict(obj))
  1315. fmt_dict(fmt, obj);
  1316. else
  1317. fmt_puts(fmt, "<unknown object>");
  1318. }
  1319. static int
  1320. pdf_sprint_obj(char *s, int n, pdf_obj *obj, int tight)
  1321. {
  1322. struct fmt fmt;
  1323. fmt.indent = 0;
  1324. fmt.col = 0;
  1325. fmt.sep = 0;
  1326. fmt.last = 0;
  1327. fmt.tight = tight;
  1328. fmt.buf = s;
  1329. fmt.cap = n;
  1330. fmt.len = 0;
  1331. fmt_obj(&fmt, obj);
  1332. if (fmt.buf && fmt.len < fmt.cap)
  1333. fmt.buf[fmt.len] = '\0';
  1334. return fmt.len;
  1335. }
  1336. int
  1337. pdf_fprint_obj(FILE *fp, pdf_obj *obj, int tight)
  1338. {
  1339. char buf[1024];
  1340. char *ptr;
  1341. int n;
  1342. n = pdf_sprint_obj(NULL, 0, obj, tight);
  1343. if ((n + 1) < sizeof buf)
  1344. {
  1345. pdf_sprint_obj(buf, sizeof buf, obj, tight);
  1346. fputs(buf, fp);
  1347. fputc('\n', fp);
  1348. }
  1349. else
  1350. {
  1351. ptr = fz_malloc(obj->ctx, n + 1);
  1352. pdf_sprint_obj(ptr, n + 1, obj, tight);
  1353. fputs(ptr, fp);
  1354. fputc('\n', fp);
  1355. fz_free(obj->ctx, ptr);
  1356. }
  1357. return n;
  1358. }
  1359. #ifndef NDEBUG
  1360. void
  1361. pdf_print_obj(pdf_obj *obj)
  1362. {
  1363. pdf_fprint_obj(stdout, obj, 0);
  1364. }
  1365. void
  1366. pdf_print_ref(pdf_obj *ref)
  1367. {
  1368. pdf_print_obj(pdf_resolve_indirect(ref));
  1369. }
  1370. #endif