filt_rle.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 239 行

C
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 + -
显示快捷键?