output.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  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. #define _LARGEFILE_SOURCE
  23. #ifndef _FILE_OFFSET_BITS
  24. #define _FILE_OFFSET_BITS 64
  25. #endif
  26. #include "mupdf/fitz.h"
  27. #include <errno.h>
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #ifdef _WIN32
  32. #include <io.h>
  33. #include <windows.h>
  34. #else
  35. #include <unistd.h>
  36. #endif
  37. static void
  38. file_write(fz_context *ctx, void *opaque, const void *buffer, size_t count)
  39. {
  40. FILE *file = opaque;
  41. size_t n;
  42. if (count == 0)
  43. return;
  44. if (count == 1)
  45. {
  46. int x = putc(((unsigned char*)buffer)[0], file);
  47. if (x == EOF && ferror(file))
  48. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot fwrite: %s", strerror(errno));
  49. return;
  50. }
  51. n = fwrite(buffer, 1, count, file);
  52. if (n < count && ferror(file))
  53. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot fwrite: %s", strerror(errno));
  54. }
  55. static void
  56. stdout_write(fz_context *ctx, void *opaque, const void *buffer, size_t count)
  57. {
  58. file_write(ctx, stdout, buffer, count);
  59. }
  60. static fz_output fz_stdout_global = {
  61. NULL,
  62. stdout_write,
  63. NULL,
  64. NULL,
  65. NULL,
  66. };
  67. fz_output *fz_stdout(fz_context *ctx)
  68. {
  69. return &fz_stdout_global;
  70. }
  71. static void
  72. stderr_write(fz_context *ctx, void *opaque, const void *buffer, size_t count)
  73. {
  74. file_write(ctx, stderr, buffer, count);
  75. }
  76. static fz_output fz_stderr_global = {
  77. NULL,
  78. stderr_write,
  79. NULL,
  80. NULL,
  81. NULL,
  82. };
  83. fz_output *fz_stderr(fz_context *ctx)
  84. {
  85. return &fz_stderr_global;
  86. }
  87. #ifdef _WIN32
  88. static void
  89. stdods_write(fz_context *ctx, void *opaque, const void *buffer, size_t count)
  90. {
  91. char *buf = fz_malloc(ctx, count+1);
  92. memcpy(buf, buffer, count);
  93. buf[count] = 0;
  94. OutputDebugStringA(buf);
  95. fz_free(ctx, buf);
  96. }
  97. static fz_output fz_stdods_global = {
  98. NULL,
  99. stdods_write,
  100. NULL,
  101. NULL,
  102. NULL,
  103. };
  104. fz_output *fz_stdods(fz_context *ctx)
  105. {
  106. return &fz_stdods_global;
  107. }
  108. #endif
  109. fz_output *fz_stddbg(fz_context *ctx)
  110. {
  111. if (ctx->stddbg)
  112. return ctx->stddbg;
  113. return fz_stderr(ctx);
  114. }
  115. void fz_set_stddbg(fz_context *ctx, fz_output *out)
  116. {
  117. if (ctx == NULL)
  118. return;
  119. ctx->stddbg = out;
  120. }
  121. static void
  122. file_seek(fz_context *ctx, void *opaque, int64_t off, int whence)
  123. {
  124. FILE *file = opaque;
  125. #ifdef _WIN32
  126. int n = _fseeki64(file, off, whence);
  127. #else
  128. int n = fseeko(file, off, whence);
  129. #endif
  130. if (n < 0)
  131. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot fseek: %s", strerror(errno));
  132. }
  133. static int64_t
  134. file_tell(fz_context *ctx, void *opaque)
  135. {
  136. FILE *file = opaque;
  137. #ifdef _WIN32
  138. int64_t off = _ftelli64(file);
  139. #else
  140. int64_t off = ftello(file);
  141. #endif
  142. if (off == -1)
  143. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot ftell: %s", strerror(errno));
  144. return off;
  145. }
  146. static void
  147. file_drop(fz_context *ctx, void *opaque)
  148. {
  149. FILE *file = opaque;
  150. int n = fclose(file);
  151. if (n < 0)
  152. fz_warn(ctx, "cannot fclose: %s", strerror(errno));
  153. }
  154. static fz_stream *
  155. file_as_stream(fz_context *ctx, void *opaque)
  156. {
  157. FILE *file = opaque;
  158. fflush(file);
  159. return fz_open_file_ptr_no_close(ctx, file);
  160. }
  161. static void file_truncate(fz_context *ctx, void *opaque)
  162. {
  163. FILE *file = opaque;
  164. fflush(file);
  165. #ifdef _WIN32
  166. {
  167. __int64 pos = _ftelli64(file);
  168. if (pos >= 0)
  169. _chsize_s(fileno(file), pos);
  170. }
  171. #else
  172. {
  173. off_t pos = ftello(file);
  174. if (pos >= 0)
  175. (void)ftruncate(fileno(file), pos);
  176. }
  177. #endif
  178. }
  179. fz_output *
  180. fz_new_output(fz_context *ctx, int bufsiz, void *state, fz_output_write_fn *write, fz_output_close_fn *close, fz_output_drop_fn *drop)
  181. {
  182. fz_output *out = NULL;
  183. fz_var(out);
  184. fz_try(ctx)
  185. {
  186. out = fz_malloc_struct(ctx, fz_output);
  187. out->state = state;
  188. out->write = write;
  189. out->close = close;
  190. out->drop = drop;
  191. if (bufsiz > 0)
  192. {
  193. out->bp = Memento_label(fz_malloc(ctx, bufsiz), "output_buf");
  194. out->wp = out->bp;
  195. out->ep = out->bp + bufsiz;
  196. }
  197. }
  198. fz_catch(ctx)
  199. {
  200. if (drop)
  201. drop(ctx, state);
  202. fz_free(ctx, out);
  203. fz_rethrow(ctx);
  204. }
  205. return out;
  206. }
  207. static void null_write(fz_context *ctx, void *opaque, const void *buffer, size_t count)
  208. {
  209. }
  210. fz_output *
  211. fz_new_output_with_path(fz_context *ctx, const char *filename, int append)
  212. {
  213. FILE *file;
  214. if (filename == NULL)
  215. fz_throw(ctx, FZ_ERROR_ARGUMENT, "no output to write to");
  216. if (!strcmp(filename, "/dev/null") || !fz_strcasecmp(filename, "nul:"))
  217. return fz_new_output(ctx, 0, NULL, null_write, NULL, NULL);
  218. /* If <append> is false, we use fopen()'s 'x' flag to force an error if
  219. * some other process creates the file immediately after we have removed
  220. * it - this avoids vulnerability where a less-privilege process can create
  221. * a link and get us to overwrite a different file. See:
  222. * https://bugs.ghostscript.com/show_bug.cgi?id=701797
  223. * http://www.open-std.org/jtc1/sc22//WG14/www/docs/n1339.pdf
  224. */
  225. #ifdef _WIN32
  226. /* Ensure we create a brand new file. We don't want to clobber our old file. */
  227. if (!append)
  228. {
  229. if (fz_remove_utf8(filename) < 0)
  230. if (errno != ENOENT)
  231. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot remove file '%s': %s", filename, strerror(errno));
  232. }
  233. #if defined(__MINGW32__) || defined(__MINGW64__)
  234. file = fz_fopen_utf8(filename, append ? "rb+" : "wb+"); /* 'x' flag not supported. */
  235. #else
  236. file = fz_fopen_utf8(filename, append ? "rb+" : "wb+x");
  237. #endif
  238. if (append)
  239. {
  240. if (file == NULL)
  241. file = fz_fopen_utf8(filename, "wb+");
  242. else
  243. fseek(file, 0, SEEK_END);
  244. }
  245. #else
  246. /* Ensure we create a brand new file. We don't want to clobber our old file. */
  247. if (!append)
  248. {
  249. if (remove(filename) < 0)
  250. if (errno != ENOENT)
  251. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot remove file '%s': %s", filename, strerror(errno));
  252. }
  253. file = fopen(filename, append ? "rb+" : "wb+x");
  254. if (file == NULL && append)
  255. file = fopen(filename, "wb+");
  256. #endif
  257. if (!file)
  258. fz_throw(ctx, FZ_ERROR_SYSTEM, "cannot open file '%s': %s", filename, strerror(errno));
  259. return fz_new_output_with_file_ptr(ctx, file);
  260. }
  261. fz_output *
  262. fz_new_output_with_file_ptr(fz_context *ctx, FILE *file)
  263. {
  264. fz_output *out;
  265. if (!file)
  266. return fz_new_output(ctx, 0, NULL, null_write, NULL, NULL);
  267. setvbuf(file, NULL, _IONBF, 0); /* we do our own buffering */
  268. out = fz_new_output(ctx, 8192, file, file_write, NULL, file_drop);
  269. out->seek = file_seek;
  270. out->tell = file_tell;
  271. out->as_stream = file_as_stream;
  272. out->truncate = file_truncate;
  273. return out;
  274. }
  275. static void
  276. buffer_write(fz_context *ctx, void *opaque, const void *data, size_t len)
  277. {
  278. fz_buffer *buffer = opaque;
  279. fz_append_data(ctx, buffer, data, len);
  280. }
  281. static void
  282. buffer_seek(fz_context *ctx, void *opaque, int64_t off, int whence)
  283. {
  284. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot seek in buffer: %s", strerror(errno));
  285. }
  286. static int64_t
  287. buffer_tell(fz_context *ctx, void *opaque)
  288. {
  289. fz_buffer *buffer = opaque;
  290. return (int64_t)buffer->len;
  291. }
  292. static void
  293. buffer_drop(fz_context *ctx, void *opaque)
  294. {
  295. fz_buffer *buffer = opaque;
  296. fz_drop_buffer(ctx, buffer);
  297. }
  298. static void
  299. buffer_reset(fz_context *ctx, void *opaque)
  300. {
  301. }
  302. fz_output *
  303. fz_new_output_with_buffer(fz_context *ctx, fz_buffer *buf)
  304. {
  305. fz_output *out = fz_new_output(ctx, 0, fz_keep_buffer(ctx, buf), buffer_write, NULL, buffer_drop);
  306. out->seek = buffer_seek;
  307. out->tell = buffer_tell;
  308. out->reset = buffer_reset;
  309. return out;
  310. }
  311. void
  312. fz_close_output(fz_context *ctx, fz_output *out)
  313. {
  314. if (out == NULL)
  315. return;
  316. fz_flush_output(ctx, out);
  317. if (!out->closed && out->close)
  318. out->close(ctx, out->state);
  319. out->closed = 1;
  320. }
  321. void
  322. fz_drop_output(fz_context *ctx, fz_output *out)
  323. {
  324. if (out)
  325. {
  326. if (!out->closed)
  327. fz_warn(ctx, "dropping unclosed output");
  328. if (out->drop)
  329. out->drop(ctx, out->state);
  330. fz_free(ctx, out->bp);
  331. if (out != &fz_stdout_global && out != &fz_stderr_global)
  332. fz_free(ctx, out);
  333. }
  334. }
  335. void
  336. fz_reset_output(fz_context *ctx, fz_output *out)
  337. {
  338. if (!out)
  339. return;
  340. if (out->reset == NULL)
  341. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot reset this output");
  342. out->reset(ctx, out->state);
  343. out->closed = 0;
  344. }
  345. void
  346. fz_seek_output(fz_context *ctx, fz_output *out, int64_t off, int whence)
  347. {
  348. if (out->seek == NULL)
  349. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot seek in unseekable output stream\n");
  350. fz_flush_output(ctx, out);
  351. out->seek(ctx, out->state, off, whence);
  352. }
  353. int64_t
  354. fz_tell_output(fz_context *ctx, fz_output *out)
  355. {
  356. if (out->tell == NULL)
  357. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot tell in untellable output stream\n");
  358. if (out->bp)
  359. return out->tell(ctx, out->state) + (out->wp - out->bp);
  360. return out->tell(ctx, out->state);
  361. }
  362. fz_stream *
  363. fz_stream_from_output(fz_context *ctx, fz_output *out)
  364. {
  365. if (out->as_stream == NULL)
  366. return NULL;
  367. fz_flush_output(ctx, out);
  368. return out->as_stream(ctx, out->state);
  369. }
  370. void
  371. fz_truncate_output(fz_context *ctx, fz_output *out)
  372. {
  373. if (out->truncate == NULL)
  374. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot truncate this output stream");
  375. fz_flush_output(ctx, out);
  376. out->truncate(ctx, out->state);
  377. }
  378. static void
  379. fz_write_emit(fz_context *ctx, void *out, int c)
  380. {
  381. fz_write_byte(ctx, out, c);
  382. }
  383. void
  384. fz_write_vprintf(fz_context *ctx, fz_output *out, const char *fmt, va_list args)
  385. {
  386. fz_format_string(ctx, out, fz_write_emit, fmt, args);
  387. }
  388. void
  389. fz_write_printf(fz_context *ctx, fz_output *out, const char *fmt, ...)
  390. {
  391. va_list args;
  392. va_start(args, fmt);
  393. fz_format_string(ctx, out, fz_write_emit, fmt, args);
  394. va_end(args);
  395. }
  396. void
  397. fz_flush_output(fz_context *ctx, fz_output *out)
  398. {
  399. fz_write_bits_sync(ctx, out);
  400. if (out->wp > out->bp)
  401. {
  402. out->write(ctx, out->state, out->bp, out->wp - out->bp);
  403. out->wp = out->bp;
  404. }
  405. }
  406. void
  407. fz_write_byte(fz_context *ctx, fz_output *out, unsigned char x)
  408. {
  409. if (out->bp)
  410. {
  411. if (out->wp == out->ep)
  412. {
  413. out->write(ctx, out->state, out->bp, out->wp - out->bp);
  414. out->wp = out->bp;
  415. }
  416. *out->wp++ = x;
  417. }
  418. else
  419. {
  420. out->write(ctx, out->state, &x, 1);
  421. }
  422. }
  423. void
  424. fz_write_char(fz_context *ctx, fz_output *out, char x)
  425. {
  426. fz_write_byte(ctx, out, (unsigned char)x);
  427. }
  428. void
  429. fz_write_data(fz_context *ctx, fz_output *out, const void *data_, size_t size)
  430. {
  431. const char *data = data_;
  432. if (out->bp)
  433. {
  434. if (size >= (size_t) (out->ep - out->bp)) /* too large for buffer */
  435. {
  436. if (out->wp > out->bp)
  437. {
  438. out->write(ctx, out->state, out->bp, out->wp - out->bp);
  439. out->wp = out->bp;
  440. }
  441. out->write(ctx, out->state, data, size);
  442. }
  443. else if (out->wp + size <= out->ep) /* fits in current buffer */
  444. {
  445. memcpy(out->wp, data, size);
  446. out->wp += size;
  447. }
  448. else /* fits if we flush first */
  449. {
  450. size_t n = out->ep - out->wp;
  451. memcpy(out->wp, data, n);
  452. out->write(ctx, out->state, out->bp, out->ep - out->bp);
  453. memcpy(out->bp, data + n, size - n);
  454. out->wp = out->bp + size - n;
  455. }
  456. }
  457. else
  458. {
  459. out->write(ctx, out->state, data, size);
  460. }
  461. }
  462. void
  463. fz_write_buffer(fz_context *ctx, fz_output *out, fz_buffer *buf)
  464. {
  465. fz_write_data(ctx, out, buf->data, buf->len);
  466. }
  467. void
  468. fz_write_string(fz_context *ctx, fz_output *out, const char *s)
  469. {
  470. fz_write_data(ctx, out, s, strlen(s));
  471. }
  472. void
  473. fz_write_int32_be(fz_context *ctx, fz_output *out, int x)
  474. {
  475. char data[4];
  476. data[0] = x>>24;
  477. data[1] = x>>16;
  478. data[2] = x>>8;
  479. data[3] = x;
  480. fz_write_data(ctx, out, data, 4);
  481. }
  482. void
  483. fz_write_uint32_be(fz_context *ctx, fz_output *out, unsigned int x)
  484. {
  485. fz_write_int32_be(ctx, out, (unsigned int)x);
  486. }
  487. void
  488. fz_write_int32_le(fz_context *ctx, fz_output *out, int x)
  489. {
  490. char data[4];
  491. data[0] = x;
  492. data[1] = x>>8;
  493. data[2] = x>>16;
  494. data[3] = x>>24;
  495. fz_write_data(ctx, out, data, 4);
  496. }
  497. void
  498. fz_write_uint32_le(fz_context *ctx, fz_output *out, unsigned int x)
  499. {
  500. fz_write_int32_le(ctx, out, (int)x);
  501. }
  502. void
  503. fz_write_int16_be(fz_context *ctx, fz_output *out, int x)
  504. {
  505. char data[2];
  506. data[0] = x>>8;
  507. data[1] = x;
  508. fz_write_data(ctx, out, data, 2);
  509. }
  510. void
  511. fz_write_uint16_be(fz_context *ctx, fz_output *out, unsigned int x)
  512. {
  513. fz_write_int16_be(ctx, out, (int)x);
  514. }
  515. void
  516. fz_write_int16_le(fz_context *ctx, fz_output *out, int x)
  517. {
  518. char data[2];
  519. data[0] = x;
  520. data[1] = x>>8;
  521. fz_write_data(ctx, out, data, 2);
  522. }
  523. void
  524. fz_write_uint16_le(fz_context *ctx, fz_output *out, unsigned int x)
  525. {
  526. fz_write_int16_le(ctx, out, (int)x);
  527. }
  528. void
  529. fz_write_float_le(fz_context *ctx, fz_output *out, float f)
  530. {
  531. union {float f; int32_t i;} u;
  532. u.f = f;
  533. fz_write_int32_le(ctx, out, u.i);
  534. }
  535. void
  536. fz_write_float_be(fz_context *ctx, fz_output *out, float f)
  537. {
  538. union {float f; int32_t i;} u;
  539. u.f = f;
  540. fz_write_int32_be(ctx, out, u.i);
  541. }
  542. void
  543. fz_write_rune(fz_context *ctx, fz_output *out, int rune)
  544. {
  545. char data[10];
  546. fz_write_data(ctx, out, data, fz_runetochar(data, rune));
  547. }
  548. void
  549. fz_write_base64(fz_context *ctx, fz_output *out, const unsigned char *data, size_t size, int newline)
  550. {
  551. static const char set[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  552. size_t i;
  553. for (i = 0; i + 3 <= size; i += 3)
  554. {
  555. int c = data[i];
  556. int d = data[i+1];
  557. int e = data[i+2];
  558. if (newline && (i & 15) == 0)
  559. fz_write_byte(ctx, out, '\n');
  560. fz_write_byte(ctx, out, set[c>>2]);
  561. fz_write_byte(ctx, out, set[((c&3)<<4)|(d>>4)]);
  562. fz_write_byte(ctx, out, set[((d&15)<<2)|(e>>6)]);
  563. fz_write_byte(ctx, out, set[e&63]);
  564. }
  565. if (size - i == 2)
  566. {
  567. int c = data[i];
  568. int d = data[i+1];
  569. fz_write_byte(ctx, out, set[c>>2]);
  570. fz_write_byte(ctx, out, set[((c&3)<<4)|(d>>4)]);
  571. fz_write_byte(ctx, out, set[((d&15)<<2)]);
  572. fz_write_byte(ctx, out, '=');
  573. }
  574. else if (size - i == 1)
  575. {
  576. int c = data[i];
  577. fz_write_byte(ctx, out, set[c>>2]);
  578. fz_write_byte(ctx, out, set[((c&3)<<4)]);
  579. fz_write_byte(ctx, out, '=');
  580. fz_write_byte(ctx, out, '=');
  581. }
  582. }
  583. void
  584. fz_write_base64_buffer(fz_context *ctx, fz_output *out, fz_buffer *buf, int newline)
  585. {
  586. unsigned char *data;
  587. size_t size = fz_buffer_storage(ctx, buf, &data);
  588. fz_write_base64(ctx, out, data, size, newline);
  589. }
  590. void
  591. fz_append_base64(fz_context *ctx, fz_buffer *out, const unsigned char *data, size_t size, int newline)
  592. {
  593. static const char set[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  594. size_t i;
  595. for (i = 0; i + 3 <= size; i += 3)
  596. {
  597. int c = data[i];
  598. int d = data[i+1];
  599. int e = data[i+2];
  600. if (newline && (i & 15) == 0)
  601. fz_append_byte(ctx, out, '\n');
  602. fz_append_byte(ctx, out, set[c>>2]);
  603. fz_append_byte(ctx, out, set[((c&3)<<4)|(d>>4)]);
  604. fz_append_byte(ctx, out, set[((d&15)<<2)|(e>>6)]);
  605. fz_append_byte(ctx, out, set[e&63]);
  606. }
  607. if (size - i == 2)
  608. {
  609. int c = data[i];
  610. int d = data[i+1];
  611. fz_append_byte(ctx, out, set[c>>2]);
  612. fz_append_byte(ctx, out, set[((c&3)<<4)|(d>>4)]);
  613. fz_append_byte(ctx, out, set[((d&15)<<2)]);
  614. fz_append_byte(ctx, out, '=');
  615. }
  616. else if (size - i == 1)
  617. {
  618. int c = data[i];
  619. fz_append_byte(ctx, out, set[c>>2]);
  620. fz_append_byte(ctx, out, set[((c&3)<<4)]);
  621. fz_append_byte(ctx, out, '=');
  622. fz_append_byte(ctx, out, '=');
  623. }
  624. }
  625. void
  626. fz_append_base64_buffer(fz_context *ctx, fz_buffer *out, fz_buffer *buf, int newline)
  627. {
  628. unsigned char *data;
  629. size_t size = fz_buffer_storage(ctx, buf, &data);
  630. fz_append_base64(ctx, out, data, size, newline);
  631. }
  632. void
  633. fz_save_buffer(fz_context *ctx, fz_buffer *buf, const char *filename)
  634. {
  635. fz_output *out = fz_new_output_with_path(ctx, filename, 0);
  636. fz_try(ctx)
  637. {
  638. fz_write_data(ctx, out, buf->data, buf->len);
  639. fz_close_output(ctx, out);
  640. }
  641. fz_always(ctx)
  642. fz_drop_output(ctx, out);
  643. fz_catch(ctx)
  644. fz_rethrow(ctx);
  645. }
  646. fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_output *out)
  647. {
  648. fz_band_writer *writer = fz_calloc(ctx, size, 1);
  649. writer->out = out;
  650. return writer;
  651. }
  652. void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum, fz_colorspace *cs, fz_separations *seps)
  653. {
  654. if (writer == NULL || writer->band == NULL)
  655. return;
  656. if (w <= 0 || h <= 0 || n <= 0 || alpha < 0 || alpha > 1)
  657. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Invalid bandwriter header dimensions/setup");
  658. writer->w = w;
  659. writer->h = h;
  660. writer->s = fz_count_active_separations(ctx, seps);
  661. writer->n = n;
  662. writer->alpha = alpha;
  663. writer->xres = xres;
  664. writer->yres = yres;
  665. writer->pagenum = pagenum;
  666. writer->line = 0;
  667. writer->seps = fz_keep_separations(ctx, seps);
  668. writer->header(ctx, writer, cs);
  669. }
  670. void fz_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_height, const unsigned char *samples)
  671. {
  672. if (writer == NULL || writer->band == NULL)
  673. return;
  674. if (writer->line + band_height > writer->h)
  675. band_height = writer->h - writer->line;
  676. if (band_height < 0) {
  677. fz_throw(ctx, FZ_ERROR_LIMIT, "Too much band data!");
  678. }
  679. if (band_height > 0) {
  680. writer->band(ctx, writer, stride, writer->line, band_height, samples);
  681. writer->line += band_height;
  682. }
  683. if (writer->line == writer->h && writer->trailer) {
  684. writer->trailer(ctx, writer);
  685. /* Protect against more band_height == 0 calls */
  686. writer->line++;
  687. }
  688. }
  689. void fz_close_band_writer(fz_context *ctx, fz_band_writer *writer)
  690. {
  691. if (writer == NULL)
  692. return;
  693. if (writer->close != NULL)
  694. writer->close(ctx, writer);
  695. writer->close = NULL;
  696. }
  697. void fz_drop_band_writer(fz_context *ctx, fz_band_writer *writer)
  698. {
  699. if (writer == NULL)
  700. return;
  701. if (writer->drop != NULL)
  702. writer->drop(ctx, writer);
  703. fz_drop_separations(ctx, writer->seps);
  704. fz_free(ctx, writer);
  705. }
  706. int fz_output_supports_stream(fz_context *ctx, fz_output *out)
  707. {
  708. return out != NULL && out->as_stream != NULL;
  709. }
  710. void fz_write_bits(fz_context *ctx, fz_output *out, unsigned int data, int num_bits)
  711. {
  712. while (num_bits)
  713. {
  714. /* How many bits will be left in the current byte after we
  715. * insert these bits? */
  716. int n = 8 - num_bits - out->buffered;
  717. if (n >= 0)
  718. {
  719. /* We can fit our data in. */
  720. out->bits |= data << n;
  721. out->buffered += num_bits;
  722. num_bits = 0;
  723. }
  724. else
  725. {
  726. /* There are 8 - out->buffered bits left to be filled. We have
  727. * num_bits to fill it with, which is more, so we need to throw
  728. * away the bottom 'num_bits - (8 - out->buffered)' bits. That's
  729. * num_bits + out->buffered - 8 = -(8 - num_bits - out_buffered) = -n */
  730. out->bits |= data >> -n;
  731. data &= ~(out->bits << -n);
  732. num_bits = -n;
  733. out->buffered = 8;
  734. }
  735. if (out->buffered == 8)
  736. {
  737. fz_write_byte(ctx, out, out->bits);
  738. out->buffered = 0;
  739. out->bits = 0;
  740. }
  741. }
  742. }
  743. void fz_write_bits_sync(fz_context *ctx, fz_output *out)
  744. {
  745. if (out->buffered == 0)
  746. return;
  747. fz_write_bits(ctx, out, 0, 8 - out->buffered);
  748. }
  749. void
  750. fz_write_stream(fz_context *ctx, fz_output *out, fz_stream *in)
  751. {
  752. size_t z;
  753. while ((z = fz_available(ctx, in, 4096)) != 0)
  754. {
  755. fz_write_data(ctx, out, in->rp, z);
  756. in->rp += z;
  757. }
  758. }