filt_rle.c.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 239 行
SVN-BASE
239 行
#include "fitz-base.h"#include "fitz-stream.h"/* TODO: rewrite! * make it non-optimal or something, * just not this horrid mess... */#define noDEBUGtypedef struct fz_rle_s fz_rle;struct fz_rle_s{ fz_filter super; int reclen; int curlen; int state; int run; unsigned char buf[128];};enum { ZERO, ONE, DIFF, SAME, END};fz_error *fz_newrle(fz_filter **fp, fz_obj *params){ FZ_NEWFILTER(fz_rle, enc, rle); if (params) enc->reclen = fz_toint(params); else enc->reclen = 0; enc->curlen = 0; enc->state = ZERO; enc->run = 0; return fz_okay;}voidfz_droprle(fz_filter *enc){}static fz_error *putone(fz_rle *enc, fz_buffer *in, fz_buffer *out){ if (out->wp + 2 >= out->ep) return fz_ioneedout;#ifdef DEBUGfprintf(stderr, "one '%c'\n", enc->buf[0]);#endif *out->wp++ = 0; *out->wp++ = enc->buf[0]; return fz_okay;}static fz_error *putsame(fz_rle *enc, fz_buffer *in, fz_buffer *out){ if (out->wp + enc->run >= out->ep) return fz_ioneedout;#ifdef DEBUGfprintf(stderr, "same %d x '%c'\n", enc->run, enc->buf[0]);#endif *out->wp++ = 257 - enc->run; *out->wp++ = enc->buf[0]; return fz_okay;}static fz_error *putdiff(fz_rle *enc, fz_buffer *in, fz_buffer *out){ int i; if (out->wp + enc->run >= out->ep) return fz_ioneedout;#ifdef DEBUGfprintf(stderr, "diff %d\n", enc->run);#endif *out->wp++ = enc->run - 1; for (i = 0; i < enc->run; i++) *out->wp++ = enc->buf[i]; return fz_okay;}static fz_error *puteod(fz_rle *enc, fz_buffer *in, fz_buffer *out){ if (out->wp + 1 >= out->ep) return fz_ioneedout;#ifdef DEBUGfprintf(stderr, "eod\n");#endif *out->wp++ = 128; return fz_okay;}static fz_error *savebuf(fz_rle *enc, fz_buffer *in, fz_buffer *out){ switch (enc->state) { case ZERO: return fz_okay; case ONE: return putone(enc, in, out); case SAME: return putsame(enc, in, out); case DIFF: return putdiff(enc, in, out); case END: return puteod(enc, in, out); default: assert(!"invalid state in rle"); return fz_okay; }}fz_error *fz_processrle(fz_filter *filter, fz_buffer *in, fz_buffer *out){ fz_rle *enc = (fz_rle*)filter; fz_error *error; unsigned char c; while (1) { if (enc->reclen && enc->curlen == enc->reclen) { error = savebuf(enc, in, out); if (error) return error;#ifdef DEBUGfprintf(stderr, "--record--\n");#endif enc->state = ZERO; enc->curlen = 0; } if (in->rp == in->wp) { if (in->eof) { if (enc->state != END) { error = savebuf(enc, in, out); if (error) return error; } enc->state = END; } else return fz_ioneedin; } c = *in->rp; switch (enc->state) { case ZERO: enc->state = ONE; enc->run = 1; enc->buf[0] = c; break; case ONE: enc->state = DIFF; enc->run = 2; enc->buf[1] = c; break; case DIFF: /* out of space */ if (enc->run == 128) { error = putdiff(enc, in, out); if (error) return error; enc->state = ONE; enc->run = 1; enc->buf[0] = c; } /* run of three that are the same */ else if ((enc->run > 1) && (c == enc->buf[enc->run - 1]) && (c == enc->buf[enc->run - 2])) { if (enc->run >= 3) { enc->run -= 2; /* skip prev two for diff run */ error = putdiff(enc, in, out); if (error) return error; } enc->state = SAME; enc->run = 3; enc->buf[0] = c; } /* keep on collecting */ else { enc->buf[enc->run++] = c; } break; case SAME: if (enc->run == 128 || c != enc->buf[0]) { error = putsame(enc, in, out); if (error) return error; enc->state = ONE; enc->run = 1; enc->buf[0] = c; } else { enc->run ++; } break; case END: error = puteod(enc, in, out); if (error) return error; return fz_iodone; } in->rp ++; enc->curlen ++; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?