|
|
1.1 root 1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
3: /* The copyright notice does not imply actual or intended publication. */
4: /* AUTHORS: */
5: /* T. Pavlidis - ATT-BL MH - first versions */
6: /* H. S. Baird - ATT-BL MH - first versions */
7:
8: /* rlelib.c - subroutines for writing/reading run-length-encoded format files.
9: BUG: Uses system I/O for speed, but sacrifices machine-independence:
10: should use fioi.h macroes instead.
11: See rle.h for summary of rle file and format of public functions.
12: Writing a rle file:
13: fd=creat()
14: RLE_put_hdr(fd,hp) - once: allocate buffers, write header
15: RLE_put_Line(fd,lp) - repeatedly
16: RLE_close(fd) - once: flush and deallocate buffers
17: Reading a rle file:
18: fd=open()
19: RLE_open(fd,hp) - once: read header, 1st line into buffer
20: RLE_get_Line(l,r) - repeatedly (on EOF, deallocates buffer)
21: The user can read line-at-a-time or run-at-a-time, but should not intermix them:
22: line-at-a-time:
23: (RLE_Line *) RLE_get_Line(l,r) - return ptr to next line with some run
24: in the interval [l,r];
25: read from opened file (NULL if EOF, abort on error)
26: allocates large buffer and frees it when done
27: run-at-a-time:
28: int RLE_get_Run(&R) - read next run into (RLE_Run) R
29: returns the line number (-1 for EOF, abort on ERROR)
30: does not allocate large buffer;
31: if only a few runs will be used, can be faster
32: */
33:
34: #include <stdio.h>
35: #define LIBC_INCL 1
36: #include "CPU.h"
37: #include "stdocr.h"
38: #include "rle.h"
39:
40: #define RLE_dbg F
41: #define dbg_rd F
42: #define dbg_wr F
43:
44: /* Treated as local static: */
45: typedef struct RLE_global {
46: int fd; /* rle file descriptor */
47: boolean eof;
48: int cy, cx; /* current line no., x-coord */
49: short runs, nrun; /* no. runs, next run in current line */
50: RLE_Line *lp; /* pointer to line (malloc space) */
51: int bpl; /* maximum no. bytes in packed rle line */
52: char *bf; /* I/O buffer (malloc space) */
53: int bfsize; /* size of buffer */
54: char *cp; /* cur. ptr, into bf */
55: } RLE_global;
56: #define Init_RLE_global {0,F,-1,-1,0,0,NULL,0,NULL,0,NULL}
57: RLE_global _RLE = Init_RLE_global;
58:
59: RLE_put_hdr( fd, rhp, bufn )
60: int fd;
61: RIC_hdr *rhp;
62: int bufn; /* minimum number of lines to buffer locally */
63: { char hdr[100];
64: int stat;
65: sprintf(hdr,"TYPE=rle\nWINDOW=%d %d %d %d\nRES=%d %d\n\n",
66: /* use half-open WINDOW convention: l&t closed, r&b open*/
67: rhp->bx.a.x,rhp->bx.a.y,rhp->bx.b.x+1,rhp->bx.b.y+1,
68: rhp->res_x,rhp->res_y);
69: if((stat=write(fd,hdr,strlen(hdr)))!=strlen(hdr)) {
70: abort("rlelib: can't put hdr, stat %d",stat);
71: };
72: _RLE.fd = fd;
73: _RLE.cy = rhp->bx.a.y-1;
74: _RLE.bpl = rhp->bx.b.x-rhp->bx.a.x+9; /* maximum bytes per line */
75: _RLE.bfsize = bufn*_RLE.bpl;
76: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
77: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
78: _RLE.cp = _RLE.bf;
79: }
80:
81: #define PUT(A,B) { if((A)<128) *(B)++ = (A); \
82: else { *(B)++ = HIGH(A) | 0200; *(B)++ = LOW(A); } \
83: }
84:
85: /* write out a non-blank line of runs */
86: RLE_put_Line(fd,rlp)
87: int fd; /* file descr (already open) */
88: RLE_Line *rlp;
89: { register char *bp;
90: short blank_lines_mny; /* the number of preceding blank lines, minus 1 */
91: register RLE_Run *rp,*ep;
92: Scoor xsofar;
93: short bytes_mny;
94: int stat; /* I/O status */
95: if((_RLE.bfsize-(_RLE.cp-_RLE.bf)) < _RLE.bpl) {
96: /* not enough room left in buffer for worst-case line */
97: RLE_flush();
98: };
99: /* leave space for (short) bytes_mny count */
100: bp=_RLE.cp+sizeof(short);
101: if((blank_lines_mny=(rlp->y-_RLE.cy-1))>0) /* blank lines were skipped */ {
102: PUT(0,bp); /* ``0 runs'' signals blank lines */
103: PUT(blank_lines_mny,bp);
104: };
105: _RLE.cy=rlp->y;
106: PUT(rlp->runs,bp);
107: xsofar=0;
108: for(rp=rlp->r,ep=rp+rlp->runs; rp!=ep; rp++) {
109: PUT(rp->xs-xsofar,bp); xsofar = rp->xs;
110: PUT(rp->xe-xsofar+1,bp); xsofar = rp->xe+1;
111: };
112: /* go back & write no. bytes at top of line */
113: *((short *) _RLE.cp) = bp-_RLE.cp-sizeof(short);
114: _RLE.cp = bp;
115: if(dbg_wr) err("RLE_put_Line y%d nh%d",_RLE.cy,bytes_mny-2);
116: };
117:
118: /* write out a set of runs */
119: RLE_put_Lines(fd,rlsp)
120: int fd; /* file descr (already open) */
121: RLE_Lines *rlsp;
122: { int i;
123: RLE_Line *rlp;
124: for(i=0,rlp=rlsp->rla; i<rlsp->mny; i++,rlp++)
125: RLE_put_Line(fd,rlp);
126: }
127:
128: RLE_flush()
129: { int bytes;
130: int stat;
131: if((bytes=(_RLE.cp-_RLE.bf))>0)
132: if(stat=write(_RLE.fd,_RLE.bf,bytes)!=bytes)
133: abort("can't write _RLE.bf[%d], status %d",bytes,stat);
134: _RLE.cp = _RLE.bf;
135: }
136:
137: RLE_close(fd)
138: int fd;
139: { RLE_flush();
140: if(_RLE.bf!=NULL) free(_RLE.bf);
141: _RLE.bf = _RLE.cp = NULL;
142: _RLE.bfsize = 0;
143: }
144:
145: /* ``open'' RLE_file for reading:
146: save filedes, read header, and read first line into buffer */
147: boolean RLE_open( fd, hp )
148: int fd;
149: RIC_hdr *hp;
150: { _RLE.fd = fd;
151: /* read header */
152: RLE_get_hdr( fd, hp );
153: if(_RLE.bf!=NULL) free(_RLE.bf);
154: _RLE.bfsize = _RLE.bpl;
155: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
156: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
157: /* read first non-blank line */
158: _RLE.cy = hp->bx.a.y-1;
159: if (!RLE_rdbf()) return(F);
160: _RLE.eof = F;
161: return(T);
162: }
163:
164: /* read next short from rle-line buffer, updating arg ptr */
165: short RLE_gshort(p)
166: char **p;
167: { register n;
168: register char *q;
169: q = *p;
170: if((*q)&0200) {
171: n = (((*q & 0177)<<8)&077400) | (*(q+1) & 0377);
172: (*p)++;
173: }
174: else n = *q;
175: (*p)++;
176: return(n);
177: }
178:
179: /* system I/O variation on fgets(3), except it replaces \n with \0,
180: and returns the number of chars read (including \0) */
181: int RLE_fgets(bf,max,fd)
182: char *bf;
183: int max;
184: int fd;
185: { char *cp;
186: int stat,mny;
187: cp=bf; mny=0;
188: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
189: if(stat!=1) return(stat);
190: else if(mny>=max) return(-1);
191: *cp='\0';
192: return(mny);
193: }
194:
195: /* read ascii header from rle file, convert to RIC_hdr,
196: return status: 1 OK, 0 EOF, -1 error */
197: int RLE_get_hdr( fd, hp )
198: int fd; /* should have been open'ed earlier */
199: RIC_hdr *hp;
200: #define HL_MAX 80
201: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
202: { char *cp,*parm,hline[HL_MAX];
203: int status,nrd;
204: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
205: while(strlen(hline)>1) {
206: if(RLE_dbg) err("hline \"%s\"",hline);
207: parm=strtok(hline,HTERM);
208: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
209: if((parm=strtok(0,HTERM))!=NULL
210: &&strcmp(parm,"rle")==0) ;
211: else return(-1);
212: }
213: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
214: /* assume half-open WINDOW: l&t closed, r&b open */
215: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.x=atoi(parm);
216: else return(-1);
217: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.y=atoi(parm);
218: else return(-1);
219: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.x=atoi(parm)-1;
220: else return(-1);
221: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.y=atoi(parm)-1;
222: else return(-1);
223: }
224: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
225: if((parm=strtok(0,HTERM))!=NULL) hp->res_x=atoi(parm);
226: else return(-1);
227: if((parm=strtok(0,HTERM))!=NULL) hp->res_y=atoi(parm);
228: else return(-1);
229: }
230: else return(-1);
231: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
232: };
233: /* maximum possible no. bytes in a packed rle line */
234: _RLE.bpl = hp->bpl = hp->bx.b.x-hp->bx.a.x+9;
235: if(dbg_rd) fprintf(stderr,"rlelib: RLE_get_hdr: %s\n",RIC_hdr_toa(hp));
236: return(1);
237: }
238:
239: /* read the next run into *Rp, and return line number
240: (-1 for EOF, abort on error) */
241: int RLE_get_Run( Rp )
242: RLE_Run *Rp;
243: { if(_RLE.nrun >= _RLE.runs) { /* no more, try to read next line */
244: if (!RLE_rdbf()) /* EOF */ return(-1);
245: };
246: /* another run */
247: Rp->xs = (_RLE.cx += RLE_gshort(&_RLE.cp));
248: Rp->xe = (_RLE.cx += RLE_gshort(&_RLE.cp)) - 1;
249: _RLE.nrun++;
250: return(_RLE.cy);
251: }
252:
253: /* Return ptr to the next line with at least one run overlapping the margins
254: [lm,rm]. The reported runs are not trimmed to fit exactly within margins.
255: If no more lines, return NULL. On error, abort */
256: RLE_Line *RLE_get_Line(lm,rm)
257: int lm, rm; /* left, right margins */
258: { register int rr; /* runs read */
259: register RLE_Run *rp; /* write ptr */
260:
261: do { if(_RLE.eof) {
262: free(_RLE.lp); _RLE.lp = NULL;
263: free(_RLE.bf); _RLE.bf = NULL;
264: return(NULL);
265: };
266: if(_RLE.lp==NULL) { /* allocate space for RLE_Line */
267: _RLE.lp = (RLE_Line *) malloc(sizeof(RLE_Line));
268: if(_RLE.lp==NULL) {
269: abort("rlelib: can't malloc RLE_Line (%d bytes)",
270: sizeof(RLE_Line));
271: };
272: };
273: _RLE.lp->y = _RLE.cy;
274: /* guaranteed to be at least one run in line */
275: rr=0; rp=_RLE.lp->r; _RLE.lp->runs=0;
276: /* skip runs that are outside left margin */
277: do RLE_get_Run(rp);
278: while((rr++ < _RLE.runs) && (rp->xe < lm));
279: /* accept runs until cross right margin */
280: while(rp->xs <= rm) {
281: _RLE.lp->runs++; /* count accepted runs */
282: if(rr++ >= _RLE.runs) break;
283: RLE_get_Run(++rp);
284: };
285: /* look ahead to next line */
286: if (!RLE_rdbf()) /* EOF */ _RLE.eof=T;
287: }
288: while(_RLE.lp->runs==0); /* as result of margins, some lines may empty */
289: return(_RLE.lp);
290: }
291:
292: /* read next line buffer - return F if EOF, abort on error
293: sideffects: sets up _RLE.cp, _RLE.cy, _RLE.cx, _RLE.runs, _RLE.nrun */
294: boolean RLE_rdbf()
295: { short nh;
296: if(dbg_rd) err("enter RLE_rdbf");
297: /* get number of bytes holding RLE of a scan line */
298: if( read(_RLE.fd,&nh,sizeof(short)) != sizeof(short)) {
299: return(F); /* normal EOF */
300: };
301: if( Readvax )
302: nh = swapshortin( nh );
303: if(dbg_rd) err("rlelib: RLE_rdbf: nh %d",nh);
304: if(nh > _RLE.bpl) {
305: abort("rlelib: too many bytes in line: %d > %d(_RLE.bpl)",
306: nh,_RLE.bpl);
307: };
308:
309: /* get those bytes */
310: if( read(_RLE.fd,_RLE.bf,nh) != nh) {
311: abort("rlelib: rle line truncated");
312: };
313: if(dbg_rd) {
314: int bi;
315: err("rlelib: RLE_rdbf: _RLE.bf[0-%d] octal:",nh-1);
316: for(bi=0;bi<nh;bi++)
317: fprintf(stderr," 0%o",0377&(_RLE.bf[bi]));
318: fprintf(stderr,"\n");
319: };
320:
321: /* decode the bytes */
322: _RLE.cp = _RLE.bf;
323: _RLE.runs = RLE_gshort(&_RLE.cp);
324: if(dbg_rd) err("rlelib: _RLE.runs %d",_RLE.runs);
325: if(_RLE.runs==0) { /* blank lines seen */
326: _RLE.cy += RLE_gshort(&_RLE.cp);
327: _RLE.runs = RLE_gshort(&_RLE.cp);
328: if(dbg_rd)
329: err("rlelib: _RLE.cy %d _RLE.runs %d",_RLE.cy,_RLE.runs);
330: };
331: if(_RLE.runs>RLE_RUNS || _RLE.runs<1) {
332: abort("rlelib: illegal no. runs %d in line",_RLE.runs);
333: };
334: _RLE.cy++;
335: if(dbg_rd) err("rlelib: RLE_rdbf: _RLE.runs %d _RLE.cy %d",_RLE.runs,_RLE.cy);
336: _RLE.cx = _RLE.nrun = 0; /* next run will be first */
337: if(dbg_rd) err("rlelib: RLE_rdbf: T exit");
338: return(T);
339: }
340:
341: /* brrl - compute a binary raster line from a run-length-encoded scanline.
342: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
343: and ending index (inclusive) of each run of black pixels (1 bits).
344: xe >= xs > xe. The runs are in strictly ascending order on xs.
345: lm & rm are the left and right margin indices of pixels, outside of which the
346: pixels are forced to be white. rm >= lm. The `lm'th pixel is written
347: into the `olm'th bit of the output raster (olm>=0).
348: rasp[] is a raser line of chars; on entry, it is assumed to have been zeroed
349: out. rasp[0] holds the leftmost byte in the line and the 001 bit of each
350: byte is the leftmost bit in that byte.
351: The user must ensure that rasp[] is at least (rm-lm+olm+9)/8 bytes long.
352: Returns the number of black pixels in the raster line.
353: NOTE: this uses the ``little-endian'' convention, in which the leftmost pixel
354: in a byte is placed in the least-significant bit (0x01). See `brrlb()' below
355: for the alternative ``big-endian'' version.
356: */
357: int brrl(runs,runa,lm,rm,olm,rasp)
358: int runs; /* number of run-segments in runa[] */
359: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
360: int lm,rm; /* left,right margin bit indices within raster */
361: int olm; /* `lm'th input pixel will be written to `olm'th bit */
362: char unsigned rasp[]; /* binary raster line (zeroed out on entry) */
363: { int pixels,bi;
364: RLE_Run r,*rp,*re;
365: pixels = 0;
366: re = (rp = (RLE_Run *) runa) + runs;
367: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
368: while(rp<re && rp->xs<=rm) {
369: /* truncate to margins */
370: if((r.xs = rp->xs)<lm) r.xs = lm;
371: if((r.xe = rp->xe)>rm) r.xe = rm;
372: /* shift to output indices */
373: r.xs += olm-lm; r.xe += olm-lm;
374: /** SLOW **/
375: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (01)<<(bi%8);
376: pixels += r.xe-r.xs+1;
377: rp++;
378: };
379: return(pixels);
380: }
381:
382: /* ``big-endian'' version of brrl: bits are packed so that the leftmost
383: pixel is placed in the high-order bit (0x80) of each byte.
384: */
385: int brrlb(runs,runa,lm,rm,olm,rasp)
386: int runs;
387: short runa[];
388: int lm,rm,olm;
389: char unsigned rasp[];
390: { int pixels,bi;
391: RLE_Run r,*rp,*re;
392: pixels = 0;
393: re = (rp = (RLE_Run *) runa) + runs;
394: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
395: while(rp<re && rp->xs<=rm) {
396: /* truncate to margins */
397: if((r.xs = rp->xs)<lm) r.xs = lm;
398: if((r.xe = rp->xe)>rm) r.xe = rm;
399: /* shift to output indices */
400: r.xs += olm-lm; r.xe += olm-lm;
401: /** SLOW **/
402: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (0200)>>(bi%8);
403: pixels += r.xe-r.xs+1;
404: rp++;
405: };
406: return(pixels);
407: }
408:
409: /* crrl - compute a character raster line from a run-length-encoded scanline.
410: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
411: and ending index (inclusive) of each run of black pixels (1 bits): xs<=xe.
412: The runs are in strictly ascending order on xs. lm & rm are the left and
413: right margin indices, outside of which pixels are forced to be white. rm >= lm.
414: rasp[] is a raster line, one unsigned char per pixel; rasp[0] holds the
415: leftmost pixel. The user must ensure that rasp[] is at least (rm-lm+1)
416: bytes long. Black pixels are encoded as 0, white as 255. Returns the number
417: of black pixels in the raster line.
418: */
419: #define WHITE_pel 0377
420: #define BLACK_pel 0000
421: int crrl(runs,runa,lm,rm,rasp)
422: int runs; /* number of run-segments in runa[] */
423: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
424: int lm,rm; /* left,right margin bit indices within raster */
425: unsigned char rasp[]; /* char raster line */
426: { int pixels,bi,wid;
427: RLE_Run r,*rp,*re;
428: unsigned char *cp,*ep;
429: wid=rm-lm+1;
430: memset(rasp,WHITE_pel,wid);
431: re = (rp = (RLE_Run *) runa) + runs;
432: while(rp<re&&rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
433: if(rp>=re) return(0);
434:
435: r = *rp; r.xs -= lm; r.xe -= lm;
436: pixels = 0;
437: do { /* truncate left,right margin */
438: if(r.xs<0) r.xs = 0;
439: if(r.xe>(wid-1)) r.xe = wid-1;
440: /* write r into raster line */
441: pixels += (r.xe-r.xs+1);
442: for(cp=rasp+r.xs,ep=rasp+r.xe; cp<=ep; cp++) *cp = BLACK_pel;
443: /* step to next run */
444: r = *(++rp); r.xs -= lm; r.xe -= lm;
445: }
446: while(r.xs<=(wid-1)&&rp<re);
447: return(pixels);
448: }
449:
450: /* trcr - threshold & run-length-encode a char raster line. `rasp' is a raster
451: line, one unsigned char per pixel: rasp[0] is the leftmost pixel in the line.
452: Pixels with value < 'thresh' are translated to black, else white.
453: Analyzes the line into a series of runs of `1's, placing them into array
454: `runs'. Observes margins: starts at `lm' bit and continues through `rm';
455: bits outside the margins are assumed 0. A `run' is two shorts (the starting &
456: ending indices of the run of `1's, inclusive). The indices are shifted
457: so that the `lm'th pixel goes to run index `olm'. Returns the number of runs.
458: NOTE: The user must ensure that: (1) margins fall within `rasp[]';
459: (2) `runp[]' is big enough to hold the worst-case no. of runs that can result
460: ((rm-lm+2)/2). The contents of the raster-line are unmodified.
461: */
462: int trcr(rasp,lm,rm,olm,thresh,runp)
463: char unsigned rasp[]; /* binary raster line (with 1 extra byte at end) */
464: int lm,rm; /* left,right margin indices within raster */
465: int olm; /* `lm' pixel goes to `olm' run index */
466: int thresh;
467: short runp[]; /* array of run-segments [xs,xe] (pairs of short) */
468: #define dbg_trcr (T)
469: { unsigned char *cp,*ep;
470: short x,*xp;
471: int cv,pv; /* current,prior binary pixel value */
472: ep=(cp=rasp+lm)+rm; x=olm; xp=runp;
473: pv=0; /* assume pixels left of 'lm' are 0 */
474: while (cp<=ep) {
475: if((*cp)<thresh) {
476: /* black pixel */
477: cv=1;
478: if(pv==0) { *xp = x; xp++; };
479: }
480: else { /* white pixel */
481: cv=0;
482: if(pv==1) { *xp = x-1; xp++; };
483: };
484: pv=cv; x++;
485: cp++;
486: };
487: if(pv==1) { *xp = x-1; xp++; }; /* assume pixels right of 'rm' is 0 */
488: return((xp-runp)/2);
489: }
490:
491: /* Transform a sequence of rle-lines using trimming, offsetting, scaling,
492: truncation, and reverse-video. Scaling may lead to interpolation or
493: decimation of lines, so an input line may be mapped into 0, 1, or more
494: output lines.
495: Input lines may be buffered, and there may be latency. To flush buffers,
496: this must be called with NULL argument at end of the sequence. Each output
497: line will be passed to function `sink()', which returns 1 if OK and 0 to quit. Quits are passed back immediately with no latency. Sink's 1st arg RLE_Line
498: *l is a line of runs in output coordinates, whose `len' is the maximum length
499: of the line. l==NULL means end of sequence.
500: Return 1 if OK, 0 to quit. A copy of *l is passed to sink().
501: a->sy is incremented for every line written to the sink, and is attached to
502: the output lines as *.y.
503: */
504: int transform_rlel(l,a,sink,sa)
505: RLE_Line *l; /* NULL if end of sequence */
506: Transform_rlel_arg *a;
507: int (*sink)(); /* takes args: (RLE_Line *), and int */
508: VOID *sa; /* passed to sink() as 2nd arg */
509: { RLE_Line m,r;
510: register RLE_Run *rp,*ep,*mp;
511: RLE_Run mr,mm,rr;
512: int rm;
513: int o_a_x,o_b_x; /* maximum output index */
514: if(l==NULL) {
515: sink(NULL,sa);
516: return(1);
517: };
518: m.len = l->len;
519: m.runs = l->runs;
520: if(a->ident) {
521: if(m.runs>0) memcpy(m.r,l->r,2*m.runs*sizeof(short));
522: m.y = a->sy;
523: if(sink(&m,sa)==0) return(0);
524: else { a->sy++;
525: return(1);
526: };
527: };
528: /* maximum permissable output bounds */
529: o_a_x = (int)((a->tr.a.x + a->off.x)*a->scl.x);
530: o_b_x = o_a_x + a->wh.x - 1;
531: if(a->sy<=((int)a->dy)) {
532: /* compute runs to be ouput: rp - input runs; mp - output runs*/
533: mp=(m.r - 1);
534: for(ep=(rp=l->r)+l->runs; rp<ep; rp++) {
535: /* trim using a->tr */
536: mr = *rp;
537: if(mr.xe < a->tr.a.x) /* off left margin */ continue;
538: if(mr.xs > a->tr.b.x) /* off right margin */ break;
539: if(mr.xs < a->tr.a.x) /* extends left too far */
540: mr.xs=a->tr.a.x;
541: if(mr.xe > a->tr.b.x) /* extends right too far */
542: mr.xe=a->tr.b.x;
543:
544: /* offset using a->off */
545: mr.xs += a->off.x;
546: mr.xe += a->off.x;
547:
548: /* expand using a->scl */
549: mr.xs = (int)(mr.xs*a->scl.x);
550: mr.xe = ((int)((mr.xe+1)*a->scl.x))-1;
551: if(mr.xe<mr.xs) mr.xe=mr.xs;
552:
553: /* truncate to maximum output width */
554: if(mr.xe<o_a_x) /* off left margin */ continue;
555: if(mr.xs>o_b_x) /* off right margin */ break;
556: if(mr.xs<o_a_x) /* extends left too far */ mr.xs=o_a_x;
557: if(mr.xe>o_b_x) /* extends right too far */ mr.xe=o_b_x;
558: /* store */
559: if(mp < m.r) /* first */ *(++mp) = mr;
560: else /* can merge with prior run? */ {
561: if(mp->xe >= (mr.xs-1)) /* yes */ mp->xe = mr.xe;
562: else /* no */ *(++mp) = mr;
563: };
564: };
565: m.runs = mp - m.r + 1;
566: m.len = a->wh.x;
567: do { m.y = a->sy;
568: if(a->rev) {
569: /* r = reverse-video(m) */
570: rp=r.r; rr.xs=o_a_x;
571: for(ep=(mp=m.r)+m.runs; mp<ep; mp++) {
572: if(rr.xs<mp->xs) {
573: rr.xe=mp->xs-1;
574: *(rp++)=rr;
575: };
576: rr.xs=mp->xe+1;
577: };
578: if(rr.xs<=o_b_x) {
579: rr.xe=o_b_x;
580: *(rp++)=rr;
581: };
582: r.runs = rp-r.r;
583: r.len = m.len;
584: r.y = m.y;
585: if(sink(&r,sa)==0) return(0);
586: }
587: else { if(sink(&m,sa)==0) return(0); };
588: a->sy++;
589: }
590: while(a->sy<=((int)a->dy));
591: };
592: a->dy += a->scl.y;
593: return(1);
594: }
595:
596: /* Insert a (copy of) the given RLE_Line in the RLE_Lines */
597: insert_rlel(rlp,rlsp)
598: RLE_Line *rlp;
599: RLE_Lines *rlsp;
600: { abort("insert_rlel: unimplemented");
601: }
602:
603: err_RLE_line(s,rl)
604: char *s; /* name */
605: RLE_Line *rl;
606: { RLE_Run *r;
607: int ri;
608: if(rl==NULL) fprintf(stderr,"RLEL %10s NULL\n",s);
609: else { fprintf(stderr,"RLEL %10s y%d r%d l%d: ",
610: s,rl->y,rl->runs,rl->len);
611: for(ri=0,r=rl->r;ri<rl->runs;ri++,r++)
612: fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
613: fprintf(stderr,"\n");
614: };
615: }
616:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.