Sigrid Solveig Haflínudóttirmake it build under 9front (thanks LordCreepity)358c45c5 years agoHistory
260 lines · 4.1 KB · C
RawDownload
/* * 2.2.9.1.1.3.1.2.4 RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM) *	http://msdn.microsoft.com/en-us/library/cc240895.aspx * 3.1.9 Interleaved RLE-Based Bitmap Compression *	http://msdn.microsoft.com/en-us/library/dd240593.aspx*/#include <u.h>#include <libc.h>#include "dat.h"#include "fns.h" enum{	Bits4=	15,	Bits5=	31,}; enum{	DWhite		= 0xFFFFFFFF,}; enum{	Bg,	Fg,	FgS,	Dith,	Fill,	Mix,	MixS,	Lit,	Spec,	Mix3,	Mix5,	Wpix,	Bpix,}; enum{	Std= 0,	Ext= 1,}; static intdecode[2][16] ={[Std]={		Bg, 	Bg, 	Fg, 	Fg,	Mix,	Mix,	Fill,	Fill,		Lit,	Lit,	-1, 	-1,	FgS,	MixS,	Dith,	-1,	},[Ext]={		Bg, 	Fg, 	Mix,	Fill,	Lit,	-1, 	FgS,	MixS,		Dith,	Mix3,	Mix5,	-1, 	-1, 	Wpix,	Bpix,	-1,	}}; static void*memfill(void *a1, ulong n1, void *a2, ulong n2){	char *s1, *s2, *e1, *e2; 	if((long)n1 < 0 || (long)n2 <= 0)		abort();	s1 = a1;	s2 = a2;	e1 = s1+n1;	e2 = s2+n2;	while(s1 < e1){		*s1++ = *s2++;		if(s2 >= e2)			s2 = a2;	}	return a1;} static void*memxor(void *a1, void *a2, ulong n){	char *s1, *s2; 	if((long)n < 0)		abort();	s1 = a1;	s2 = a2;	while(n > 0){		*s1++ ^= *s2++;		n--;	}	return a1;} uchar*unrle(uchar* d, int nd, uchar* s, int ns, int bpl, int pixelsize){	int t, hdr, code, bits, len, wasline1, wasbg;	uchar pen[4], dpen[8], wpen[4], *p, *ep, *wp, *we;	uint sreg; 	p = s;	ep = s+ns;	wp = d;	we = d+nd;	wasbg = 0;	wasline1 = 1;	iputl(pen, DWhite);	iputl(wpen, DWhite); 	while(p < ep){		hdr = *p++;		code = hdr>>4;		if(code != Bits4){			t = decode[Std][code];			if(code>>2 == 3)				bits = Bits4;			else				bits = Bits5;			len = hdr&bits;			if(t==Mix || t==MixS){				if(len == 0)					len = 1+*p++;				else					len *= 8;			}else{				if(len == 0)					len = 1+bits+*p++;			}		}else{			code = hdr&Bits4;			if(code < 9){				len = igets(p);				p += 2;			}else				len = 0;			t = decode[Ext][code];		}		len *= pixelsize;		if(wp+len > we){		   Overrun:			werrstr("unrle: output buffer is %zd bytes short", (intptr)(wp+len-we));			return nil;		} 		if(t != Bg)			wasbg = 0;		if(wasline1 && wp-bpl >= d){			wasline1 = 0;			wasbg = 0;		} 		switch(t){		default:			werrstr("unrle: bad decode");			return nil;		case Lit:			memmove(wp, p, len);			p += len;			break;		case Bg:			if(wasbg){				memmove(wp, pen, pixelsize);				if(wp-bpl >= d)					memxor(wp, wp-bpl, pixelsize);				wp += pixelsize;				len -= pixelsize;			}			if(wp-bpl >= d){				while(len>bpl){					memmove(wp, wp-bpl, bpl);					wp += bpl;					len -= bpl;				}				memmove(wp, wp-bpl, len);			}else				memset(wp, len, 0);			wasbg = 1;			break;		case FgS:			memmove(pen, p, pixelsize);			p += pixelsize;			/* fall through */		case Fg:			memfill(wp, len, pen, pixelsize);			if(wp-bpl >= d)				memxor(wp, wp-bpl, len);			break;		case Mix3:			sreg = 3;			bits = 8;			len = 8*pixelsize;			goto case_MixAll;		case Mix5:			sreg = 5;			bits = 8;			len = 8*pixelsize;			goto case_MixAll;		case MixS:			memmove(pen, p, pixelsize);			p += pixelsize;			/* fall through */		case Mix:			sreg = 0;			bits = 0;			/* fall through */		case_MixAll:			if(wp+len > we)				goto Overrun;			while(len > 0){				if(bits == 0){					sreg = *p++;					bits = 8;				}				if(sreg&1){					memmove(wp, pen, pixelsize);					if(wp-bpl >= d)						memxor(wp, wp-bpl, pixelsize);				}else{					if(wp-bpl >= d)						memmove(wp, wp-bpl, pixelsize);					else						memset(wp, pixelsize, 0);				}				wp += pixelsize;				len -= pixelsize;				sreg >>= 1;				bits--;			}			break;		case Fill:			memmove(dpen, p, pixelsize);			p += pixelsize;			memfill(wp, len, dpen, pixelsize);			break;		case Dith:			len *= 2;			if(wp+len > we)				goto Overrun;			memmove(dpen, p, pixelsize);			memmove(dpen+pixelsize, p+pixelsize, pixelsize);			p += 2*pixelsize;			memfill(wp, len, dpen, 2*pixelsize);			break;		case Wpix:			len = pixelsize;			if(wp+len > we)				goto Overrun;			memmove(wp, wpen, pixelsize);			break;		case Bpix:			len = pixelsize;			if(wp+len > we)				goto Overrun;			memset(wp, pixelsize, 0);			break;		}		wp += len;	}	return wp;}