Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/fitz/encode-basic.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 | |
| 23 #include "mupdf/fitz.h" | |
| 24 | |
| 25 #include "z-imp.h" | |
| 26 | |
| 27 #include <limits.h> | |
| 28 | |
| 29 struct ahx | |
| 30 { | |
| 31 fz_output *chain; | |
| 32 int column; | |
| 33 }; | |
| 34 | |
| 35 static void ahx_write(fz_context *ctx, void *opaque, const void *data, size_t n) | |
| 36 { | |
| 37 static const char tohex[17] = "0123456789ABCDEF"; | |
| 38 struct ahx *state = opaque; | |
| 39 const unsigned char *p = data; | |
| 40 while (n-- > 0) | |
| 41 { | |
| 42 int c = *p++; | |
| 43 fz_write_byte(ctx, state->chain, tohex[(c>>4) & 15]); | |
| 44 fz_write_byte(ctx, state->chain, tohex[(c) & 15]); | |
| 45 state->column += 2; | |
| 46 if (state->column == 64) | |
| 47 { | |
| 48 fz_write_byte(ctx, state->chain, '\n'); | |
| 49 state->column = 0; | |
| 50 } | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 static void ahx_close(fz_context *ctx, void *opaque) | |
| 55 { | |
| 56 struct ahx *state = opaque; | |
| 57 fz_write_byte(ctx, state->chain, '>'); | |
| 58 } | |
| 59 | |
| 60 static void ahx_reset(fz_context *ctx, void *opaque) | |
| 61 { | |
| 62 struct ahx *state = opaque; | |
| 63 state->column = 0; | |
| 64 fz_reset_output(ctx, state->chain); | |
| 65 } | |
| 66 | |
| 67 static void ahx_drop(fz_context *ctx, void *opaque) | |
| 68 { | |
| 69 struct ahx *state = opaque; | |
| 70 fz_free(ctx, state); | |
| 71 } | |
| 72 | |
| 73 fz_output * | |
| 74 fz_new_asciihex_output(fz_context *ctx, fz_output *chain) | |
| 75 { | |
| 76 fz_output *out; | |
| 77 struct ahx *state = fz_malloc_struct(ctx, struct ahx); | |
| 78 | |
| 79 state->chain = chain; | |
| 80 state->column = 0; | |
| 81 out = fz_new_output(ctx, 512, state, ahx_write, ahx_close, ahx_drop); | |
| 82 out->reset = ahx_reset; | |
| 83 | |
| 84 return out; | |
| 85 } | |
| 86 | |
| 87 struct a85 | |
| 88 { | |
| 89 fz_output *chain; | |
| 90 int column; | |
| 91 unsigned int word, n; | |
| 92 }; | |
| 93 | |
| 94 static void a85_flush(fz_context *ctx, struct a85 *state) | |
| 95 { | |
| 96 unsigned int v1, v2, v3, v4, v5; | |
| 97 | |
| 98 v5 = state->word; | |
| 99 v4 = v5 / 85; | |
| 100 v3 = v4 / 85; | |
| 101 v2 = v3 / 85; | |
| 102 v1 = v2 / 85; | |
| 103 | |
| 104 if (state->column >= 70) | |
| 105 { | |
| 106 fz_write_byte(ctx, state->chain, '\n'); | |
| 107 state->column = 0; | |
| 108 } | |
| 109 | |
| 110 if (state->n == 4) | |
| 111 { | |
| 112 if (state->word == 0) | |
| 113 { | |
| 114 fz_write_byte(ctx, state->chain, 'z'); | |
| 115 state->column += 1; | |
| 116 } | |
| 117 else | |
| 118 { | |
| 119 fz_write_byte(ctx, state->chain, (v1 % 85) + '!'); | |
| 120 fz_write_byte(ctx, state->chain, (v2 % 85) + '!'); | |
| 121 fz_write_byte(ctx, state->chain, (v3 % 85) + '!'); | |
| 122 fz_write_byte(ctx, state->chain, (v4 % 85) + '!'); | |
| 123 fz_write_byte(ctx, state->chain, (v5 % 85) + '!'); | |
| 124 state->column += 5; | |
| 125 } | |
| 126 } | |
| 127 else if (state->n == 3) | |
| 128 { | |
| 129 fz_write_byte(ctx, state->chain, (v2 % 85) + '!'); | |
| 130 fz_write_byte(ctx, state->chain, (v3 % 85) + '!'); | |
| 131 fz_write_byte(ctx, state->chain, (v4 % 85) + '!'); | |
| 132 fz_write_byte(ctx, state->chain, (v5 % 85) + '!'); | |
| 133 state->column += 4; | |
| 134 } | |
| 135 else if (state->n == 2) | |
| 136 { | |
| 137 fz_write_byte(ctx, state->chain, (v3 % 85) + '!'); | |
| 138 fz_write_byte(ctx, state->chain, (v4 % 85) + '!'); | |
| 139 fz_write_byte(ctx, state->chain, (v5 % 85) + '!'); | |
| 140 state->column += 3; | |
| 141 } | |
| 142 else if (state->n == 1) | |
| 143 { | |
| 144 fz_write_byte(ctx, state->chain, (v4 % 85) + '!'); | |
| 145 fz_write_byte(ctx, state->chain, (v5 % 85) + '!'); | |
| 146 state->column += 2; | |
| 147 } | |
| 148 | |
| 149 state->word = 0; | |
| 150 state->n = 0; | |
| 151 } | |
| 152 | |
| 153 static void a85_write(fz_context *ctx, void *opaque, const void *data, size_t n) | |
| 154 { | |
| 155 struct a85 *state = opaque; | |
| 156 const unsigned char *p = data; | |
| 157 while (n-- > 0) | |
| 158 { | |
| 159 unsigned int c = *p++; | |
| 160 if (state->n == 4) | |
| 161 a85_flush(ctx, state); | |
| 162 state->word = (state->word << 8) | c; | |
| 163 state->n++; | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 static void a85_close(fz_context *ctx, void *opaque) | |
| 168 { | |
| 169 struct a85 *state = opaque; | |
| 170 a85_flush(ctx, state); | |
| 171 fz_write_byte(ctx, state->chain, '~'); | |
| 172 fz_write_byte(ctx, state->chain, '>'); | |
| 173 } | |
| 174 | |
| 175 static void a85_reset(fz_context *ctx, void *opaque) | |
| 176 { | |
| 177 struct a85 *state = opaque; | |
| 178 state->column = 0; | |
| 179 state->word = 0; | |
| 180 state->n = 0; | |
| 181 fz_reset_output(ctx, state->chain); | |
| 182 } | |
| 183 | |
| 184 static void a85_drop(fz_context *ctx, void *opaque) | |
| 185 { | |
| 186 struct a85 *state = opaque; | |
| 187 fz_free(ctx, state); | |
| 188 } | |
| 189 | |
| 190 fz_output * | |
| 191 fz_new_ascii85_output(fz_context *ctx, fz_output *chain) | |
| 192 { | |
| 193 fz_output *out; | |
| 194 struct a85 *state = fz_malloc_struct(ctx, struct a85); | |
| 195 | |
| 196 state->chain = chain; | |
| 197 state->column = 0; | |
| 198 state->word = 0; | |
| 199 state->n = 0; | |
| 200 out = fz_new_output(ctx, 512, state, a85_write, a85_close, a85_drop); | |
| 201 out->reset = a85_reset; | |
| 202 | |
| 203 return out; | |
| 204 } | |
| 205 | |
| 206 struct rle | |
| 207 { | |
| 208 fz_output *chain; | |
| 209 int state; | |
| 210 int run; | |
| 211 unsigned char buf[128]; | |
| 212 }; | |
| 213 | |
| 214 enum { ZERO, ONE, DIFF, SAME }; | |
| 215 | |
| 216 static void rle_flush_same(fz_context *ctx, struct rle *enc) | |
| 217 { | |
| 218 fz_write_byte(ctx, enc->chain, 257 - enc->run); | |
| 219 fz_write_byte(ctx, enc->chain, enc->buf[0]); | |
| 220 } | |
| 221 | |
| 222 static void rle_flush_diff(fz_context *ctx, struct rle *enc) | |
| 223 { | |
| 224 fz_write_byte(ctx, enc->chain, enc->run - 1); | |
| 225 fz_write_data(ctx, enc->chain, enc->buf, enc->run); | |
| 226 } | |
| 227 | |
| 228 static void rle_write(fz_context *ctx, void *opaque, const void *data, size_t n) | |
| 229 { | |
| 230 struct rle *enc = opaque; | |
| 231 const unsigned char *p = data; | |
| 232 while (n-- > 0) | |
| 233 { | |
| 234 int c = *p++; | |
| 235 switch (enc->state) | |
| 236 { | |
| 237 case ZERO: | |
| 238 enc->state = ONE; | |
| 239 enc->run = 1; | |
| 240 enc->buf[0] = c; | |
| 241 break; | |
| 242 | |
| 243 case ONE: | |
| 244 enc->state = DIFF; | |
| 245 enc->run = 2; | |
| 246 enc->buf[1] = c; | |
| 247 break; | |
| 248 | |
| 249 case DIFF: | |
| 250 /* Max run length */ | |
| 251 if (enc->run == 128) | |
| 252 { | |
| 253 rle_flush_diff(ctx, enc); | |
| 254 enc->state = ONE; | |
| 255 enc->run = 1; | |
| 256 enc->buf[0] = c; | |
| 257 } | |
| 258 /* Run of three same */ | |
| 259 else if ((enc->run >= 2) && (c == enc->buf[enc->run-1]) && (c == enc->buf[enc->run-2])) | |
| 260 { | |
| 261 if (enc->run >= 3) { | |
| 262 enc->run -= 2; /* skip last two in previous run */ | |
| 263 rle_flush_diff(ctx, enc); | |
| 264 } | |
| 265 enc->state = SAME; | |
| 266 enc->run = 3; | |
| 267 enc->buf[0] = c; | |
| 268 } | |
| 269 else | |
| 270 { | |
| 271 enc->buf[enc->run] = c; | |
| 272 enc->run++; | |
| 273 } | |
| 274 break; | |
| 275 | |
| 276 case SAME: | |
| 277 if ((enc->run == 128) || (c != enc->buf[0])) | |
| 278 { | |
| 279 rle_flush_same(ctx, enc); | |
| 280 enc->state = ONE; | |
| 281 enc->run = 1; | |
| 282 enc->buf[0] = c; | |
| 283 } | |
| 284 else | |
| 285 { | |
| 286 enc->run++; | |
| 287 } | |
| 288 } | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 static void rle_close(fz_context *ctx, void *opaque) | |
| 293 { | |
| 294 struct rle *enc = opaque; | |
| 295 switch (enc->state) | |
| 296 { | |
| 297 case ZERO: break; | |
| 298 case ONE: rle_flush_diff(ctx, enc); break; | |
| 299 case DIFF: rle_flush_diff(ctx, enc); break; | |
| 300 case SAME: rle_flush_same(ctx, enc); break; | |
| 301 } | |
| 302 fz_write_byte(ctx, enc->chain, 128); | |
| 303 } | |
| 304 | |
| 305 static void rle_reset(fz_context *ctx, void *opaque) | |
| 306 { | |
| 307 struct rle *enc = opaque; | |
| 308 enc->state = ZERO; | |
| 309 enc->run = 0; | |
| 310 fz_reset_output(ctx, enc->chain); | |
| 311 } | |
| 312 | |
| 313 static void rle_drop(fz_context *ctx, void *opaque) | |
| 314 { | |
| 315 struct rle *enc = opaque; | |
| 316 fz_free(ctx, enc); | |
| 317 } | |
| 318 | |
| 319 fz_output * | |
| 320 fz_new_rle_output(fz_context *ctx, fz_output *chain) | |
| 321 { | |
| 322 fz_output *out; | |
| 323 struct rle *enc = fz_malloc_struct(ctx, struct rle); | |
| 324 | |
| 325 enc->chain = chain; | |
| 326 enc->state = ZERO; | |
| 327 enc->run = 0; | |
| 328 out = fz_new_output(ctx, 4096, enc, rle_write, rle_close, rle_drop); | |
| 329 out->reset = rle_reset; | |
| 330 | |
| 331 return out; | |
| 332 } | |
| 333 | |
| 334 struct arc4 | |
| 335 { | |
| 336 fz_output *chain; | |
| 337 fz_arc4 arc4; | |
| 338 fz_arc4 arc4_orig; | |
| 339 }; | |
| 340 | |
| 341 static void arc4_write(fz_context *ctx, void *opaque, const void *data, size_t n) | |
| 342 { | |
| 343 struct arc4 *state = opaque; | |
| 344 const unsigned char *p = data; | |
| 345 unsigned char buffer[256]; | |
| 346 while (n > 0) | |
| 347 { | |
| 348 size_t x = (n > sizeof buffer) ? sizeof buffer : n; | |
| 349 fz_arc4_encrypt(&state->arc4, buffer, p, x); | |
| 350 fz_write_data(ctx, state->chain, buffer, x); | |
| 351 p += x; | |
| 352 n -= x; | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 static void arc4_reset(fz_context *ctx, void *opaque) | |
| 357 { | |
| 358 struct arc4 *state = opaque; | |
| 359 memcpy(&state->arc4, &state->arc4_orig, sizeof(state->arc4)); | |
| 360 fz_reset_output(ctx, state->chain); | |
| 361 } | |
| 362 | |
| 363 static void arc4_drop(fz_context *ctx, void *opaque) | |
| 364 { | |
| 365 fz_free(ctx, opaque); | |
| 366 } | |
| 367 | |
| 368 fz_output * | |
| 369 fz_new_arc4_output(fz_context *ctx, fz_output *chain, unsigned char *key, size_t keylen) | |
| 370 { | |
| 371 fz_output *out; | |
| 372 struct arc4 *state = fz_malloc_struct(ctx, struct arc4); | |
| 373 | |
| 374 state->chain = chain; | |
| 375 fz_arc4_init(&state->arc4, key, keylen); | |
| 376 memcpy(&state->arc4_orig, &state->arc4, sizeof(state->arc4)); | |
| 377 out = fz_new_output(ctx, 256, state, arc4_write, NULL, arc4_drop); | |
| 378 out->reset = arc4_reset; | |
| 379 | |
| 380 return out; | |
| 381 } | |
| 382 | |
| 383 struct deflate | |
| 384 { | |
| 385 fz_output *chain; | |
| 386 z_stream z; | |
| 387 uInt bufsize; | |
| 388 unsigned char *buf; | |
| 389 }; | |
| 390 | |
| 391 static void deflate_write(fz_context *ctx, void *opaque, const void *data, size_t n) | |
| 392 { | |
| 393 struct deflate *state = opaque; | |
| 394 const unsigned char *p = data; | |
| 395 uLong newbufsizeLong; | |
| 396 uInt newbufsize; | |
| 397 int err; | |
| 398 | |
| 399 newbufsizeLong = n >= UINT_MAX ? UINT_MAX : deflateBound(&state->z, (uLong)n); | |
| 400 newbufsize = (uInt)(newbufsizeLong >= UINT_MAX ? UINT_MAX : newbufsizeLong); | |
| 401 | |
| 402 if (state->buf == NULL) | |
| 403 { | |
| 404 state->buf = Memento_label(fz_malloc(ctx, newbufsize), "deflate_buffer"); | |
| 405 state->bufsize = newbufsize; | |
| 406 } | |
| 407 else if (newbufsize > state->bufsize) | |
| 408 { | |
| 409 state->buf = Memento_label(fz_realloc(ctx, state->buf, newbufsize), "deflate_buffer"); | |
| 410 state->bufsize = newbufsize; | |
| 411 } | |
| 412 | |
| 413 while (n > 0) | |
| 414 { | |
| 415 state->z.avail_in = n <= UINT_MAX ? (uInt)n : UINT_MAX; | |
| 416 state->z.next_in = (unsigned char *) p; | |
| 417 n -= state->z.avail_in; | |
| 418 p += state->z.avail_in; | |
| 419 | |
| 420 do | |
| 421 { | |
| 422 state->z.next_out = state->buf; | |
| 423 state->z.avail_out = state->bufsize; | |
| 424 err = deflate(&state->z, Z_NO_FLUSH); | |
| 425 if (err != Z_OK) | |
| 426 fz_throw(ctx, FZ_ERROR_LIBRARY, "zlib compression failed: %d", err); | |
| 427 if (state->z.avail_out < state->bufsize) | |
| 428 fz_write_data(ctx, state->chain, state->buf, state->bufsize - state->z.avail_out); | |
| 429 } while (state->z.avail_in > 0); | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 static void deflate_close(fz_context *ctx, void *opaque) | |
| 434 { | |
| 435 struct deflate *state = opaque; | |
| 436 int err; | |
| 437 | |
| 438 state->z.next_in = NULL; | |
| 439 state->z.avail_in = 0; | |
| 440 do | |
| 441 { | |
| 442 state->z.next_out = state->buf; | |
| 443 state->z.avail_out = state->bufsize; | |
| 444 err = deflate(&state->z, Z_FINISH); | |
| 445 if (state->z.avail_out < state->bufsize) | |
| 446 fz_write_data(ctx, state->chain, state->buf, state->bufsize - state->z.avail_out); | |
| 447 } while (err == Z_OK); | |
| 448 | |
| 449 if (err != Z_STREAM_END) | |
| 450 fz_throw(ctx, FZ_ERROR_LIBRARY, "zlib compression failed: %d", err); | |
| 451 } | |
| 452 | |
| 453 static void deflate_reset(fz_context *ctx, void *opaque) | |
| 454 { | |
| 455 struct deflate *state = opaque; | |
| 456 int err = deflateReset(&state->z); | |
| 457 if (err != Z_OK) | |
| 458 fz_throw(ctx, FZ_ERROR_LIBRARY, "zlib reset failed: %d", err); | |
| 459 fz_reset_output(ctx, state->chain); | |
| 460 } | |
| 461 | |
| 462 static void deflate_drop(fz_context *ctx, void *opaque) | |
| 463 { | |
| 464 struct deflate *state = opaque; | |
| 465 (void)deflateEnd(&state->z); | |
| 466 fz_free(ctx, state->buf); | |
| 467 fz_free(ctx, state); | |
| 468 } | |
| 469 | |
| 470 fz_output * | |
| 471 fz_new_deflate_output(fz_context *ctx, fz_output *chain, int effort, int raw) | |
| 472 { | |
| 473 fz_output *out; | |
| 474 int err; | |
| 475 struct deflate *state = fz_malloc_struct(ctx, struct deflate); | |
| 476 | |
| 477 state->chain = chain; | |
| 478 state->z.opaque = ctx; | |
| 479 state->z.zalloc = fz_zlib_alloc; | |
| 480 state->z.zfree = fz_zlib_free; | |
| 481 err = deflateInit2(&state->z, effort, Z_DEFLATED, raw ? -15 : 15, 8, Z_DEFAULT_STRATEGY); | |
| 482 if (err != Z_OK) | |
| 483 { | |
| 484 (void)deflateEnd(&state->z); | |
| 485 fz_free(ctx, state); | |
| 486 fz_throw(ctx, FZ_ERROR_LIBRARY, "zlib deflateInit2 failed: %d", err); | |
| 487 } | |
| 488 out = fz_new_output(ctx, 8192, state, deflate_write, deflate_close, deflate_drop); | |
| 489 out->reset = deflate_reset; | |
| 490 | |
| 491 return out; | |
| 492 } |
