device.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. // Copyright (C) 2004-2025 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include <string.h>
  24. fz_device *
  25. fz_new_device_of_size(fz_context *ctx, int size)
  26. {
  27. fz_device *dev = Memento_label(fz_calloc(ctx, 1, size), "fz_device");
  28. dev->refs = 1;
  29. return dev;
  30. }
  31. static void
  32. fz_disable_device(fz_context *ctx, fz_device *dev)
  33. {
  34. dev->close_device = NULL;
  35. dev->fill_path = NULL;
  36. dev->stroke_path = NULL;
  37. dev->clip_path = NULL;
  38. dev->clip_stroke_path = NULL;
  39. dev->fill_text = NULL;
  40. dev->stroke_text = NULL;
  41. dev->clip_text = NULL;
  42. dev->clip_stroke_text = NULL;
  43. dev->ignore_text = NULL;
  44. dev->fill_shade = NULL;
  45. dev->fill_image = NULL;
  46. dev->fill_image_mask = NULL;
  47. dev->clip_image_mask = NULL;
  48. dev->pop_clip = NULL;
  49. dev->begin_mask = NULL;
  50. dev->end_mask = NULL;
  51. dev->begin_group = NULL;
  52. dev->end_group = NULL;
  53. dev->begin_tile = NULL;
  54. dev->end_tile = NULL;
  55. dev->render_flags = NULL;
  56. dev->set_default_colorspaces = NULL;
  57. dev->begin_layer = NULL;
  58. dev->end_layer = NULL;
  59. dev->begin_structure = NULL;
  60. dev->end_structure = NULL;
  61. dev->begin_metatext = NULL;
  62. dev->end_metatext = NULL;
  63. }
  64. void
  65. fz_close_device(fz_context *ctx, fz_device *dev)
  66. {
  67. if (dev == NULL)
  68. return;
  69. fz_try(ctx)
  70. {
  71. if (dev->close_device)
  72. dev->close_device(ctx, dev);
  73. }
  74. fz_always(ctx)
  75. fz_disable_device(ctx, dev);
  76. fz_catch(ctx)
  77. fz_rethrow(ctx);
  78. }
  79. fz_device *
  80. fz_keep_device(fz_context *ctx, fz_device *dev)
  81. {
  82. return fz_keep_imp(ctx, dev, &dev->refs);
  83. }
  84. void
  85. fz_drop_device(fz_context *ctx, fz_device *dev)
  86. {
  87. if (fz_drop_imp(ctx, dev, &dev->refs))
  88. {
  89. if (dev->close_device)
  90. fz_warn(ctx, "dropping unclosed device");
  91. if (dev->drop_device)
  92. dev->drop_device(ctx, dev);
  93. fz_free(ctx, dev->container);
  94. fz_free(ctx, dev);
  95. }
  96. }
  97. void
  98. fz_enable_device_hints(fz_context *ctx, fz_device *dev, int hints)
  99. {
  100. dev->hints |= hints;
  101. }
  102. void
  103. fz_disable_device_hints(fz_context *ctx, fz_device *dev, int hints)
  104. {
  105. dev->hints &= ~hints;
  106. }
  107. static void
  108. push_clip_stack(fz_context *ctx, fz_device *dev, fz_rect rect, int type)
  109. {
  110. if (dev->container_len == dev->container_cap)
  111. {
  112. int newmax = dev->container_cap * 2;
  113. if (newmax == 0)
  114. newmax = 4;
  115. dev->container = fz_realloc_array(ctx, dev->container, newmax, fz_device_container_stack);
  116. dev->container_cap = newmax;
  117. }
  118. if (dev->container_len == 0)
  119. dev->container[0].scissor = rect;
  120. else
  121. {
  122. dev->container[dev->container_len].scissor = fz_intersect_rect(dev->container[dev->container_len-1].scissor, rect);
  123. }
  124. dev->container[dev->container_len].type = type;
  125. dev->container[dev->container_len].user = 0;
  126. dev->container_len++;
  127. }
  128. static void
  129. pop_clip_stack(fz_context *ctx, fz_device *dev, int type)
  130. {
  131. if (dev->container_len == 0 || dev->container[dev->container_len-1].type != type)
  132. {
  133. fz_disable_device(ctx, dev);
  134. fz_throw(ctx, FZ_ERROR_ARGUMENT, "device calls unbalanced");
  135. }
  136. dev->container_len--;
  137. }
  138. static void
  139. pop_push_clip_stack(fz_context *ctx, fz_device *dev, int pop_type, int push_type)
  140. {
  141. if (dev->container_len == 0 || dev->container[dev->container_len-1].type != pop_type)
  142. {
  143. fz_disable_device(ctx, dev);
  144. fz_throw(ctx, FZ_ERROR_ARGUMENT, "device calls unbalanced");
  145. }
  146. dev->container[dev->container_len-1].type = push_type;
  147. }
  148. void
  149. fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
  150. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  151. {
  152. if (dev->fill_path)
  153. {
  154. fz_try(ctx)
  155. dev->fill_path(ctx, dev, path, even_odd, ctm, colorspace, color, alpha, color_params);
  156. fz_catch(ctx)
  157. {
  158. fz_disable_device(ctx, dev);
  159. fz_rethrow(ctx);
  160. }
  161. }
  162. }
  163. void
  164. fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm,
  165. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  166. {
  167. if (dev->stroke_path)
  168. {
  169. fz_try(ctx)
  170. dev->stroke_path(ctx, dev, path, stroke, ctm, colorspace, color, alpha, color_params);
  171. fz_catch(ctx)
  172. {
  173. fz_disable_device(ctx, dev);
  174. fz_rethrow(ctx);
  175. }
  176. }
  177. }
  178. void
  179. fz_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
  180. {
  181. fz_rect bbox = fz_bound_path(ctx, path, NULL, ctm);
  182. bbox = fz_intersect_rect(bbox, scissor);
  183. push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
  184. if (dev->clip_path)
  185. {
  186. fz_try(ctx)
  187. dev->clip_path(ctx, dev, path, even_odd, ctm, scissor);
  188. fz_catch(ctx)
  189. {
  190. fz_disable_device(ctx, dev);
  191. fz_rethrow(ctx);
  192. }
  193. }
  194. }
  195. void
  196. fz_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  197. {
  198. fz_rect bbox = fz_bound_path(ctx, path, stroke, ctm);
  199. bbox = fz_intersect_rect(bbox, scissor);
  200. push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
  201. if (dev->clip_stroke_path)
  202. {
  203. fz_try(ctx)
  204. dev->clip_stroke_path(ctx, dev, path, stroke, ctm, scissor);
  205. fz_catch(ctx)
  206. {
  207. fz_disable_device(ctx, dev);
  208. fz_rethrow(ctx);
  209. }
  210. }
  211. }
  212. void
  213. fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
  214. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  215. {
  216. if (dev->fill_text)
  217. {
  218. fz_try(ctx)
  219. dev->fill_text(ctx, dev, text, ctm, colorspace, color, alpha, color_params);
  220. fz_catch(ctx)
  221. {
  222. fz_disable_device(ctx, dev);
  223. fz_rethrow(ctx);
  224. }
  225. }
  226. }
  227. void
  228. fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
  229. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  230. {
  231. if (dev->stroke_text)
  232. {
  233. fz_try(ctx)
  234. dev->stroke_text(ctx, dev, text, stroke, ctm, colorspace, color, alpha, color_params);
  235. fz_catch(ctx)
  236. {
  237. fz_disable_device(ctx, dev);
  238. fz_rethrow(ctx);
  239. }
  240. }
  241. }
  242. void
  243. fz_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
  244. {
  245. fz_rect bbox = fz_bound_text(ctx, text, NULL, ctm);
  246. bbox = fz_intersect_rect(bbox, scissor);
  247. push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
  248. if (dev->clip_text)
  249. {
  250. fz_try(ctx)
  251. dev->clip_text(ctx, dev, text, ctm, scissor);
  252. fz_catch(ctx)
  253. {
  254. fz_disable_device(ctx, dev);
  255. fz_rethrow(ctx);
  256. }
  257. }
  258. }
  259. void
  260. fz_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  261. {
  262. fz_rect bbox = fz_bound_text(ctx, text, stroke, ctm);
  263. bbox = fz_intersect_rect(bbox, scissor);
  264. push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
  265. if (dev->clip_stroke_text)
  266. {
  267. fz_try(ctx)
  268. dev->clip_stroke_text(ctx, dev, text, stroke, ctm, scissor);
  269. fz_catch(ctx)
  270. {
  271. fz_disable_device(ctx, dev);
  272. fz_rethrow(ctx);
  273. }
  274. }
  275. }
  276. void
  277. fz_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
  278. {
  279. if (dev->ignore_text)
  280. {
  281. fz_try(ctx)
  282. dev->ignore_text(ctx, dev, text, ctm);
  283. fz_catch(ctx)
  284. {
  285. fz_disable_device(ctx, dev);
  286. fz_rethrow(ctx);
  287. }
  288. }
  289. }
  290. void
  291. fz_pop_clip(fz_context *ctx, fz_device *dev)
  292. {
  293. pop_clip_stack(ctx, dev, fz_device_container_stack_is_clip);
  294. if (dev->pop_clip)
  295. {
  296. fz_try(ctx)
  297. dev->pop_clip(ctx, dev);
  298. fz_catch(ctx)
  299. {
  300. fz_disable_device(ctx, dev);
  301. fz_rethrow(ctx);
  302. }
  303. }
  304. }
  305. void
  306. fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
  307. {
  308. if (dev->fill_shade)
  309. {
  310. fz_try(ctx)
  311. dev->fill_shade(ctx, dev, shade, ctm, alpha, color_params);
  312. fz_catch(ctx)
  313. {
  314. fz_disable_device(ctx, dev);
  315. fz_rethrow(ctx);
  316. }
  317. }
  318. }
  319. void
  320. fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
  321. {
  322. if (image->colorspace == NULL)
  323. fz_throw(ctx, FZ_ERROR_ARGUMENT, "argument to fill image must be a color image");
  324. if (dev->fill_image)
  325. {
  326. fz_try(ctx)
  327. dev->fill_image(ctx, dev, image, ctm, alpha, color_params);
  328. fz_catch(ctx)
  329. {
  330. fz_disable_device(ctx, dev);
  331. fz_rethrow(ctx);
  332. }
  333. }
  334. }
  335. void
  336. fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
  337. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  338. {
  339. if (dev->fill_image_mask)
  340. {
  341. fz_try(ctx)
  342. dev->fill_image_mask(ctx, dev, image, ctm, colorspace, color, alpha, color_params);
  343. fz_catch(ctx)
  344. {
  345. fz_disable_device(ctx, dev);
  346. fz_rethrow(ctx);
  347. }
  348. }
  349. }
  350. void
  351. fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
  352. {
  353. fz_rect bbox = fz_transform_rect(fz_unit_rect, ctm);
  354. bbox = fz_intersect_rect(bbox, scissor);
  355. push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
  356. if (dev->clip_image_mask)
  357. {
  358. fz_try(ctx)
  359. dev->clip_image_mask(ctx, dev, image, ctm, scissor);
  360. fz_catch(ctx)
  361. {
  362. fz_disable_device(ctx, dev);
  363. fz_rethrow(ctx);
  364. }
  365. }
  366. }
  367. void
  368. fz_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, const float *bc, fz_color_params color_params)
  369. {
  370. push_clip_stack(ctx, dev, area, fz_device_container_stack_is_mask);
  371. if (dev->begin_mask)
  372. {
  373. fz_try(ctx)
  374. dev->begin_mask(ctx, dev, area, luminosity, colorspace, bc, color_params);
  375. fz_catch(ctx)
  376. {
  377. fz_disable_device(ctx, dev);
  378. fz_rethrow(ctx);
  379. }
  380. }
  381. }
  382. void
  383. fz_end_mask_tr(fz_context *ctx, fz_device *dev, fz_function *fn)
  384. {
  385. pop_push_clip_stack(ctx, dev, fz_device_container_stack_is_mask, fz_device_container_stack_is_clip);
  386. if (dev->end_mask)
  387. {
  388. fz_try(ctx)
  389. dev->end_mask(ctx, dev, fn);
  390. fz_catch(ctx)
  391. {
  392. fz_disable_device(ctx, dev);
  393. fz_rethrow(ctx);
  394. }
  395. }
  396. }
  397. void
  398. fz_end_mask(fz_context *ctx, fz_device *dev)
  399. {
  400. fz_end_mask_tr(ctx, dev, NULL);
  401. }
  402. void
  403. fz_begin_group(fz_context *ctx, fz_device *dev, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
  404. {
  405. push_clip_stack(ctx, dev, area, fz_device_container_stack_is_group);
  406. if (dev->begin_group)
  407. {
  408. fz_try(ctx)
  409. dev->begin_group(ctx, dev, area, cs, isolated, knockout, blendmode, alpha);
  410. fz_catch(ctx)
  411. {
  412. fz_disable_device(ctx, dev);
  413. fz_rethrow(ctx);
  414. }
  415. }
  416. }
  417. void
  418. fz_end_group(fz_context *ctx, fz_device *dev)
  419. {
  420. pop_clip_stack(ctx, dev, fz_device_container_stack_is_group);
  421. if (dev->end_group)
  422. {
  423. fz_try(ctx)
  424. dev->end_group(ctx, dev);
  425. fz_catch(ctx)
  426. {
  427. fz_disable_device(ctx, dev);
  428. fz_rethrow(ctx);
  429. }
  430. }
  431. }
  432. void
  433. fz_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
  434. {
  435. (void)fz_begin_tile_id(ctx, dev, area, view, xstep, ystep, ctm, 0);
  436. }
  437. int
  438. fz_begin_tile_id(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
  439. {
  440. int result = 0;
  441. push_clip_stack(ctx, dev, area, fz_device_container_stack_is_tile);
  442. if (xstep < 0)
  443. xstep = -xstep;
  444. if (ystep < 0)
  445. ystep = -ystep;
  446. if (dev->begin_tile)
  447. {
  448. fz_try(ctx)
  449. result = dev->begin_tile(ctx, dev, area, view, xstep, ystep, ctm, id);
  450. fz_catch(ctx)
  451. {
  452. fz_disable_device(ctx, dev);
  453. fz_rethrow(ctx);
  454. }
  455. }
  456. return result;
  457. }
  458. void
  459. fz_end_tile(fz_context *ctx, fz_device *dev)
  460. {
  461. pop_clip_stack(ctx, dev, fz_device_container_stack_is_tile);
  462. if (dev->end_tile)
  463. {
  464. fz_try(ctx)
  465. dev->end_tile(ctx, dev);
  466. fz_catch(ctx)
  467. {
  468. fz_disable_device(ctx, dev);
  469. fz_rethrow(ctx);
  470. }
  471. }
  472. }
  473. void
  474. fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
  475. {
  476. if (dev->render_flags)
  477. {
  478. fz_try(ctx)
  479. dev->render_flags(ctx, dev, set, clear);
  480. fz_catch(ctx)
  481. {
  482. fz_disable_device(ctx, dev);
  483. fz_rethrow(ctx);
  484. }
  485. }
  486. }
  487. void
  488. fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
  489. {
  490. if (dev->set_default_colorspaces)
  491. {
  492. fz_try(ctx)
  493. dev->set_default_colorspaces(ctx, dev, default_cs);
  494. fz_catch(ctx)
  495. {
  496. fz_disable_device(ctx, dev);
  497. fz_rethrow(ctx);
  498. }
  499. }
  500. }
  501. void fz_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
  502. {
  503. if (dev->begin_layer)
  504. {
  505. fz_try(ctx)
  506. dev->begin_layer(ctx, dev, layer_name);
  507. fz_catch(ctx)
  508. {
  509. fz_disable_device(ctx, dev);
  510. fz_rethrow(ctx);
  511. }
  512. }
  513. }
  514. void fz_end_layer(fz_context *ctx, fz_device *dev)
  515. {
  516. if (dev->end_layer)
  517. {
  518. fz_try(ctx)
  519. dev->end_layer(ctx, dev);
  520. fz_catch(ctx)
  521. {
  522. fz_disable_device(ctx, dev);
  523. fz_rethrow(ctx);
  524. }
  525. }
  526. }
  527. void fz_begin_structure(fz_context *ctx, fz_device *dev, fz_structure str, const char *raw, int idx)
  528. {
  529. if (dev->begin_structure)
  530. {
  531. fz_try(ctx)
  532. dev->begin_structure(ctx, dev, str, raw, idx);
  533. fz_catch(ctx)
  534. {
  535. fz_disable_device(ctx, dev);
  536. fz_rethrow(ctx);
  537. }
  538. }
  539. }
  540. void fz_end_structure(fz_context *ctx, fz_device *dev)
  541. {
  542. if (dev->end_structure)
  543. {
  544. fz_try(ctx)
  545. dev->end_structure(ctx, dev);
  546. fz_catch(ctx)
  547. {
  548. fz_disable_device(ctx, dev);
  549. fz_rethrow(ctx);
  550. }
  551. }
  552. }
  553. void fz_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *meta_text)
  554. {
  555. if (dev->begin_metatext)
  556. {
  557. fz_try(ctx)
  558. dev->begin_metatext(ctx, dev, meta, meta_text);
  559. fz_catch(ctx)
  560. {
  561. fz_disable_device(ctx, dev);
  562. fz_rethrow(ctx);
  563. }
  564. }
  565. }
  566. void fz_end_metatext(fz_context *ctx, fz_device *dev)
  567. {
  568. if (dev->end_metatext)
  569. {
  570. fz_try(ctx)
  571. dev->end_metatext(ctx, dev);
  572. fz_catch(ctx)
  573. {
  574. fz_disable_device(ctx, dev);
  575. fz_rethrow(ctx);
  576. }
  577. }
  578. }
  579. fz_rect
  580. fz_device_current_scissor(fz_context *ctx, fz_device *dev)
  581. {
  582. if (dev->container_len > 0)
  583. return dev->container[dev->container_len-1].scissor;
  584. return fz_infinite_rect;
  585. }
  586. const char *
  587. fz_structure_to_string(fz_structure type)
  588. {
  589. switch (type)
  590. {
  591. default:
  592. return "Invalid";
  593. case FZ_STRUCTURE_DOCUMENT:
  594. return "Document";
  595. case FZ_STRUCTURE_PART:
  596. return "Part";
  597. case FZ_STRUCTURE_ART:
  598. return "Art";
  599. case FZ_STRUCTURE_SECT:
  600. return "Sect";
  601. case FZ_STRUCTURE_DIV:
  602. return "Div";
  603. case FZ_STRUCTURE_BLOCKQUOTE:
  604. return "BlockQuote";
  605. case FZ_STRUCTURE_CAPTION:
  606. return "Caption";
  607. case FZ_STRUCTURE_TOC:
  608. return "TOC";
  609. case FZ_STRUCTURE_TOCI:
  610. return "TOCI";
  611. case FZ_STRUCTURE_INDEX:
  612. return "Index";
  613. case FZ_STRUCTURE_NONSTRUCT:
  614. return "NonDtruct";
  615. case FZ_STRUCTURE_PRIVATE:
  616. return "Private";
  617. /* Grouping elements (PDF 2.0 - Table 364) */
  618. case FZ_STRUCTURE_DOCUMENTFRAGMENT:
  619. return "DocumentFragment";
  620. /* Grouping elements (PDF 2.0 - Table 365) */
  621. case FZ_STRUCTURE_ASIDE:
  622. return "Aside";
  623. /* Grouping elements (PDF 2.0 - Table 366) */
  624. case FZ_STRUCTURE_TITLE:
  625. return "Title";
  626. case FZ_STRUCTURE_FENOTE:
  627. return "FENote";
  628. /* Grouping elements (PDF 2.0 - Table 367) */
  629. case FZ_STRUCTURE_SUB:
  630. return "Sub";
  631. /* Paragraphlike elements (PDF 1.7 - Table 10.21) */
  632. case FZ_STRUCTURE_P:
  633. return "P";
  634. case FZ_STRUCTURE_H:
  635. return "H";
  636. case FZ_STRUCTURE_H1:
  637. return "H1";
  638. case FZ_STRUCTURE_H2:
  639. return "H2";
  640. case FZ_STRUCTURE_H3:
  641. return "H3";
  642. case FZ_STRUCTURE_H4:
  643. return "H4";
  644. case FZ_STRUCTURE_H5:
  645. return "H5";
  646. case FZ_STRUCTURE_H6:
  647. return "H6";
  648. /* List elements (PDF 1.7 - Table 10.23) */
  649. case FZ_STRUCTURE_LIST:
  650. return "L";
  651. case FZ_STRUCTURE_LISTITEM:
  652. return "LI";
  653. case FZ_STRUCTURE_LABEL:
  654. return "Lbl";
  655. case FZ_STRUCTURE_LISTBODY:
  656. return "LBody";
  657. /* Table elements (PDF 1.7 - Table 10.24) */
  658. case FZ_STRUCTURE_TABLE:
  659. return "Table";
  660. case FZ_STRUCTURE_TR:
  661. return "TR";
  662. case FZ_STRUCTURE_TH:
  663. return "TH";
  664. case FZ_STRUCTURE_TD:
  665. return "TD";
  666. case FZ_STRUCTURE_THEAD:
  667. return "THead";
  668. case FZ_STRUCTURE_TBODY:
  669. return "TBody";
  670. case FZ_STRUCTURE_TFOOT:
  671. return "TFoot";
  672. /* Inline elements (PDF 1.7 - Table 10.25) */
  673. case FZ_STRUCTURE_SPAN:
  674. return "Span";
  675. case FZ_STRUCTURE_QUOTE:
  676. return "Quote";
  677. case FZ_STRUCTURE_NOTE:
  678. return "Note";
  679. case FZ_STRUCTURE_REFERENCE:
  680. return "Reference";
  681. case FZ_STRUCTURE_BIBENTRY:
  682. return "BibEntry";
  683. case FZ_STRUCTURE_CODE:
  684. return "Code";
  685. case FZ_STRUCTURE_LINK:
  686. return "Link";
  687. case FZ_STRUCTURE_ANNOT:
  688. return "Annot";
  689. /* Inline elements (PDF 2.0 - Table 368) */
  690. case FZ_STRUCTURE_EM:
  691. return "Em";
  692. case FZ_STRUCTURE_STRONG:
  693. return "Strong";
  694. /* Ruby inline element (PDF 1.7 - Table 10.26) */
  695. case FZ_STRUCTURE_RUBY:
  696. return "Ruby";
  697. case FZ_STRUCTURE_RB:
  698. return "RB";
  699. case FZ_STRUCTURE_RT:
  700. return "RT";
  701. case FZ_STRUCTURE_RP:
  702. return "RP";
  703. /* Warichu inline element (PDF 1.7 - Table 10.26) */
  704. case FZ_STRUCTURE_WARICHU:
  705. return "Warichu";
  706. case FZ_STRUCTURE_WT:
  707. return "WT";
  708. case FZ_STRUCTURE_WP:
  709. return "WP";
  710. /* Illustration elements (PDF 1.7 - Table 10.27) */
  711. case FZ_STRUCTURE_FIGURE:
  712. return "Figure";
  713. case FZ_STRUCTURE_FORMULA:
  714. return "Formula";
  715. case FZ_STRUCTURE_FORM:
  716. return "Form";
  717. /* Artifact structure type (PDF 2.0 - Table 375) */
  718. case FZ_STRUCTURE_ARTIFACT:
  719. return "Artifact";
  720. }
  721. }
  722. fz_structure
  723. fz_structure_from_string(const char *str)
  724. {
  725. if (!strcmp(str, "Document")) return FZ_STRUCTURE_DOCUMENT;
  726. if (!strcmp(str, "Part")) return FZ_STRUCTURE_PART;
  727. if (!strcmp(str, "Art")) return FZ_STRUCTURE_ART;
  728. if (!strcmp(str, "Sect")) return FZ_STRUCTURE_SECT;
  729. if (!strcmp(str, "Div")) return FZ_STRUCTURE_DIV;
  730. if (!strcmp(str, "BlockQuote")) return FZ_STRUCTURE_BLOCKQUOTE;
  731. if (!strcmp(str, "Caption")) return FZ_STRUCTURE_CAPTION;
  732. if (!strcmp(str, "TOC")) return FZ_STRUCTURE_TOC;
  733. if (!strcmp(str, "TOCI")) return FZ_STRUCTURE_TOCI;
  734. if (!strcmp(str, "Index")) return FZ_STRUCTURE_INDEX;
  735. if (!strcmp(str, "NonStruct")) return FZ_STRUCTURE_NONSTRUCT;
  736. if (!strcmp(str, "Private")) return FZ_STRUCTURE_PRIVATE;
  737. if (!strcmp(str, "P")) return FZ_STRUCTURE_P;
  738. if (!strcmp(str, "H")) return FZ_STRUCTURE_H;
  739. if (!strcmp(str, "H1")) return FZ_STRUCTURE_H1;
  740. if (!strcmp(str, "H2")) return FZ_STRUCTURE_H2;
  741. if (!strcmp(str, "H3")) return FZ_STRUCTURE_H3;
  742. if (!strcmp(str, "H4")) return FZ_STRUCTURE_H4;
  743. if (!strcmp(str, "H5")) return FZ_STRUCTURE_H5;
  744. if (!strcmp(str, "H6")) return FZ_STRUCTURE_H6;
  745. if (!strcmp(str, "L")) return FZ_STRUCTURE_LIST;
  746. if (!strcmp(str, "LI")) return FZ_STRUCTURE_LISTITEM;
  747. if (!strcmp(str, "Lbl")) return FZ_STRUCTURE_LABEL;
  748. if (!strcmp(str, "LBody")) return FZ_STRUCTURE_LISTBODY;
  749. if (!strcmp(str, "Table")) return FZ_STRUCTURE_TABLE;
  750. if (!strcmp(str, "TR")) return FZ_STRUCTURE_TR;
  751. if (!strcmp(str, "TH")) return FZ_STRUCTURE_TH;
  752. if (!strcmp(str, "TD")) return FZ_STRUCTURE_TD;
  753. if (!strcmp(str, "THead")) return FZ_STRUCTURE_THEAD;
  754. if (!strcmp(str, "TBody")) return FZ_STRUCTURE_TBODY;
  755. if (!strcmp(str, "TFoot")) return FZ_STRUCTURE_TFOOT;
  756. if (!strcmp(str, "Span")) return FZ_STRUCTURE_SPAN;
  757. if (!strcmp(str, "Quote")) return FZ_STRUCTURE_QUOTE;
  758. if (!strcmp(str, "Note")) return FZ_STRUCTURE_NOTE;
  759. if (!strcmp(str, "Reference")) return FZ_STRUCTURE_REFERENCE;
  760. if (!strcmp(str, "BibEntry")) return FZ_STRUCTURE_BIBENTRY;
  761. if (!strcmp(str, "Code")) return FZ_STRUCTURE_CODE;
  762. if (!strcmp(str, "Link")) return FZ_STRUCTURE_LINK;
  763. if (!strcmp(str, "Annot")) return FZ_STRUCTURE_ANNOT;
  764. if (!strcmp(str, "Ruby")) return FZ_STRUCTURE_RUBY;
  765. if (!strcmp(str, "RB")) return FZ_STRUCTURE_RB;
  766. if (!strcmp(str, "RT")) return FZ_STRUCTURE_RT;
  767. if (!strcmp(str, "RP")) return FZ_STRUCTURE_RP;
  768. if (!strcmp(str, "Warichu")) return FZ_STRUCTURE_WARICHU;
  769. if (!strcmp(str, "WT")) return FZ_STRUCTURE_WT;
  770. if (!strcmp(str, "WP")) return FZ_STRUCTURE_WP;
  771. if (!strcmp(str, "Figure")) return FZ_STRUCTURE_FIGURE;
  772. if (!strcmp(str, "Formula")) return FZ_STRUCTURE_FORMULA;
  773. if (!strcmp(str, "Form")) return FZ_STRUCTURE_FORM;
  774. return FZ_STRUCTURE_INVALID;
  775. }
  776. fz_function *
  777. fz_keep_function(fz_context *ctx, fz_function *func)
  778. {
  779. return fz_keep_storable(ctx, &func->storable);
  780. }
  781. void
  782. fz_drop_function(fz_context *ctx, fz_function *func)
  783. {
  784. fz_drop_storable(ctx, &func->storable);
  785. }
  786. size_t
  787. fz_function_size(fz_context *ctx, fz_function *func)
  788. {
  789. return (func ? func->size : 0);
  790. }
  791. void
  792. fz_eval_function(fz_context *ctx, fz_function *func, const float *in, int inlen, float *out, int outlen)
  793. {
  794. float fakein[FZ_FUNCTION_MAX_M];
  795. float fakeout[FZ_FUNCTION_MAX_N];
  796. int i;
  797. if (inlen < func->m)
  798. {
  799. for (i = 0; i < inlen; ++i)
  800. fakein[i] = in[i];
  801. for (; i < func->m; ++i)
  802. fakein[i] = 0;
  803. in = fakein;
  804. }
  805. if (outlen < func->n)
  806. {
  807. func->eval(ctx, func, in, fakeout);
  808. for (i = 0; i < outlen; ++i)
  809. out[i] = fakeout[i];
  810. }
  811. else
  812. {
  813. func->eval(ctx, func, in, out);
  814. for (i = func->n; i < outlen; ++i)
  815. out[i] = 0;
  816. }
  817. }
  818. fz_function *
  819. fz_new_function_of_size(fz_context *ctx, int size, size_t size2, int m, int n, fz_function_eval_fn *eval, fz_store_drop_fn *drop)
  820. {
  821. fz_function *fn = fz_calloc(ctx, 1, size);
  822. FZ_INIT_STORABLE(fn, 1, drop);
  823. fn->eval = eval;
  824. fn->m = m;
  825. fn->n = n;
  826. return fn;
  827. }