From ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad Mon Sep 17 00:00:00 2001 From: rsc Date: Tue, 30 Sep 2003 17:47:42 +0000 Subject: [PATCH] Initial import. --- src/cmd/mk/NOTICE | 27 +++ src/cmd/mk/README | 7 + src/cmd/mk/bufblock.c | 88 ++++++++ src/cmd/mk/job.c | 33 +++ src/cmd/mk/mk.pdf | Bin 0 -> 69685 bytes src/cmd/sam/README | 29 +++ src/cmd/sam/_libc.h | 40 ++++ src/cmd/sam/err | 39 ++++ src/cmd/sam/plumb.h | 17 ++ src/cmd/sam/string.c | 193 +++++++++++++++++ src/cmd/sam/sys.c | 60 ++++++ src/cmd/sam/util.c | 54 +++++ src/libdraw/allocimagemix.c | 43 ++++ src/libdraw/bezier.c | 244 ++++++++++++++++++++++ src/libdraw/border.c | 21 ++ src/libdraw/cloadimage.c | 49 +++++ src/libdraw/computil.c | 38 ++++ src/libdraw/debug.c | 16 ++ src/libdraw/defont.c | 402 ++++++++++++++++++++++++++++++++++++ src/libdraw/draw.c | 69 +++++++ src/libdraw/drawrepl.c | 23 +++ src/libdraw/egetrect.c | 116 +++++++++++ src/libdraw/freesubfont.c | 17 ++ src/libdraw/getdefont.c | 60 ++++++ src/libdraw/getrect.c | 133 ++++++++++++ src/libdraw/icossin.c | 140 +++++++++++++ src/libdraw/icossin2.c | 261 +++++++++++++++++++++++ src/libdraw/line.c | 35 ++++ src/libdraw/loadimage.c | 54 +++++ src/libdraw/mkfont.c | 55 +++++ src/libdraw/newwindow.c | 27 +++ src/libdraw/poly.c | 87 ++++++++ src/libdraw/rectclip.c | 25 +++ src/libdraw/replclipr.c | 21 ++ src/libdraw/rgb.c | 99 +++++++++ src/libdraw/stringbg.c | 51 +++++ src/libdraw/stringsubfont.c | 65 ++++++ src/libdraw/test.c | 44 ++++ src/libdraw/window.c | 214 +++++++++++++++++++ src/libdraw/writeimage.c | 185 +++++++++++++++++ src/libdraw/writesubfont.c | 45 ++++ 41 files changed, 3226 insertions(+) create mode 100644 src/cmd/mk/NOTICE create mode 100644 src/cmd/mk/README create mode 100644 src/cmd/mk/bufblock.c create mode 100644 src/cmd/mk/job.c create mode 100644 src/cmd/mk/mk.pdf create mode 100644 src/cmd/sam/README create mode 100644 src/cmd/sam/_libc.h create mode 100644 src/cmd/sam/err create mode 100644 src/cmd/sam/plumb.h create mode 100644 src/cmd/sam/string.c create mode 100644 src/cmd/sam/sys.c create mode 100644 src/cmd/sam/util.c create mode 100644 src/libdraw/allocimagemix.c create mode 100644 src/libdraw/bezier.c create mode 100644 src/libdraw/border.c create mode 100644 src/libdraw/cloadimage.c create mode 100644 src/libdraw/computil.c create mode 100644 src/libdraw/debug.c create mode 100644 src/libdraw/defont.c create mode 100644 src/libdraw/draw.c create mode 100644 src/libdraw/drawrepl.c create mode 100644 src/libdraw/egetrect.c create mode 100644 src/libdraw/freesubfont.c create mode 100644 src/libdraw/getdefont.c create mode 100644 src/libdraw/getrect.c create mode 100644 src/libdraw/icossin.c create mode 100644 src/libdraw/icossin2.c create mode 100644 src/libdraw/line.c create mode 100644 src/libdraw/loadimage.c create mode 100644 src/libdraw/mkfont.c create mode 100644 src/libdraw/newwindow.c create mode 100644 src/libdraw/poly.c create mode 100644 src/libdraw/rectclip.c create mode 100644 src/libdraw/replclipr.c create mode 100644 src/libdraw/rgb.c create mode 100644 src/libdraw/stringbg.c create mode 100644 src/libdraw/stringsubfont.c create mode 100644 src/libdraw/test.c create mode 100644 src/libdraw/window.c create mode 100644 src/libdraw/writeimage.c create mode 100644 src/libdraw/writesubfont.c diff --git a/src/cmd/mk/NOTICE b/src/cmd/mk/NOTICE new file mode 100644 index 00000000..9911f992 --- /dev/null +++ b/src/cmd/mk/NOTICE @@ -0,0 +1,27 @@ +Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. +Portions Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved. +Portions Copyright © 1997-1999 Vita Nuova Limited. All rights reserved. +Portions Copyright © 2000-2002 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved. + +Under a licence agreement with Lucent Technologies Inc. effective 1st March 2000, +Vita Nuova Holdings Limited has the right to determine (within a specified scope) +the form and content of sublicences for this software. + +Vita Nuova Holdings Limited now makes this software available as Free +Software under the terms of the `GNU General Public LIcense, Version 2' +(see the file LICENCE or http://www.fsf.org/copyleft/gpl.html for +the full terms and conditions). One of the conditions of that licence +is that you must keep intact all notices that refer to that licence and to the absence of +of any warranty: for this software, note that includes this NOTICE file in particular. + +This suite of programs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +`GNU General Public License' for more details. + +This copyright NOTICE applies to all files in this directory and +subdirectories, unless another copyright notice appears in a given +file or subdirectory. If you take code from this software to use in +other programs, you must somehow include with it an appropriate +copyright notice that includes the copyright notice and the other +notices above. diff --git a/src/cmd/mk/README b/src/cmd/mk/README new file mode 100644 index 00000000..3bd11ff2 --- /dev/null +++ b/src/cmd/mk/README @@ -0,0 +1,7 @@ +This is a Unix port of mk, +originally done for the Inferno operating system. + +Russ Cox repackaged this to build as a standalone +Unix program. Send comments about packaging to +Russ Cox + diff --git a/src/cmd/mk/bufblock.c b/src/cmd/mk/bufblock.c new file mode 100644 index 00000000..979403bc --- /dev/null +++ b/src/cmd/mk/bufblock.c @@ -0,0 +1,88 @@ +#include "mk.h" + +static Bufblock *freelist; +#define QUANTA 4096 + +Bufblock * +newbuf(void) +{ + Bufblock *p; + + if (freelist) { + p = freelist; + freelist = freelist->next; + } else { + p = (Bufblock *) Malloc(sizeof(Bufblock)); + p->start = Malloc(QUANTA*sizeof(*p->start)); + p->end = p->start+QUANTA; + } + p->current = p->start; + *p->start = 0; + p->next = 0; + return p; +} + +void +freebuf(Bufblock *p) +{ + p->next = freelist; + freelist = p; +} + +void +growbuf(Bufblock *p) +{ + int n; + Bufblock *f; + char *cp; + + n = p->end-p->start+QUANTA; + /* search the free list for a big buffer */ + for (f = freelist; f; f = f->next) { + if (f->end-f->start >= n) { + memcpy(f->start, p->start, p->end-p->start); + cp = f->start; + f->start = p->start; + p->start = cp; + cp = f->end; + f->end = p->end; + p->end = cp; + f->current = f->start; + break; + } + } + if (!f) { /* not found - grow it */ + p->start = Realloc(p->start, n); + p->end = p->start+n; + } + p->current = p->start+n-QUANTA; +} + +void +bufcpy(Bufblock *buf, char *cp, int n) +{ + + while (n--) + insert(buf, *cp++); +} + +void +insert(Bufblock *buf, int c) +{ + + if (buf->current >= buf->end) + growbuf(buf); + *buf->current++ = c; +} + +void +rinsert(Bufblock *buf, Rune r) +{ + int n; + + n = runelen(r); + if (buf->current+n > buf->end) + growbuf(buf); + runetochar(buf->current, &r); + buf->current += n; +} diff --git a/src/cmd/mk/job.c b/src/cmd/mk/job.c new file mode 100644 index 00000000..cee93760 --- /dev/null +++ b/src/cmd/mk/job.c @@ -0,0 +1,33 @@ +#include "mk.h" + +Job * +newjob(Rule *r, Node *nlist, char *stem, char **match, Word *pre, Word *npre, Word *tar, Word *atar) +{ + register Job *j; + + j = (Job *)Malloc(sizeof(Job)); + j->r = r; + j->n = nlist; + j->stem = stem; + j->match = match; + j->p = pre; + j->np = npre; + j->t = tar; + j->at = atar; + j->nproc = -1; + j->next = 0; + return(j); +} + +void +dumpj(char *s, Job *j, int all) +{ + Bprint(&bout, "%s\n", s); + while(j){ + Bprint(&bout, "job@%ld: r=%ld n=%ld stem='%s' nproc=%d\n", + j, j->r, j->n, j->stem, j->nproc); + Bprint(&bout, "\ttarget='%s' alltarget='%s' prereq='%s' nprereq='%s'\n", + wtos(j->t, ' '), wtos(j->at, ' '), wtos(j->p, ' '), wtos(j->np, ' ')); + j = all? j->next : 0; + } +} diff --git a/src/cmd/mk/mk.pdf b/src/cmd/mk/mk.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d7b68c76db9a229565833f12b4ea20aea22cf0ef GIT binary patch literal 69685 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 literal 0 HcmV?d00001 diff --git a/src/cmd/sam/README b/src/cmd/sam/README new file mode 100644 index 00000000..b78a89da --- /dev/null +++ b/src/cmd/sam/README @@ -0,0 +1,29 @@ +This is sam (not including samterm) from the 4th edition of Plan 9, +with changes so that it can be compiled under unix. +(Tested on Solaris 7 and Debian 3.0r1.) + +Some extra libraries are needed. First, fetch libutf-2.0 and libfmt-2.0 +from + http://pdos.lcs.mit.edu/~rsc/software/ + +(Beware that in libfmt/fmt.c there is a line that says: + 'u', __ifmt, /* in Plan 9, __flagfmt */ +Thus, sam will have to fmtinstall the other thing. Other ported programs +may have to do the same. The fmt library should probably print messages +about bad format characters to stderr, since no one seems to check the +return codes.) + +Compile and install those two libraries. +Set PREFIX in the Makefile to match, then compile sam. + +Your C compiler will emit many complaints of the form: + sam.c:496: warning: passing arg 1 of `bufread' from incompatible pointer type + +This is because the Plan 9 compiler has a slightly different (better, +ala Oberon) type system than ISO C. Popular compilers generate the right +code, so in an act of civil disobediance I changed just enough to get +it to compile, but left the type errors in. Now the next C standard can +adopt this extension, because at least one important C program uses it! + +-- Scott Schwartz, 4 July 2003 + diff --git a/src/cmd/sam/_libc.h b/src/cmd/sam/_libc.h new file mode 100644 index 00000000..65618918 --- /dev/null +++ b/src/cmd/sam/_libc.h @@ -0,0 +1,40 @@ +#define __USE_UNIX98 // for pread/pwrite, supposedly +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utf.h" +#include "fmt.h" + +#define nil 0 +#define dup dup2 +#define exec execv +#define seek lseek +#define getwd getcwd +#define USED(a) +#define SET(a) + +enum { + OREAD = 0, + OWRITE = 1, + ORDWR = 2, + OCEXEC = 4, + ORCLOSE = 8 +}; + +enum { + ERRMAX = 255 +}; + +void exits(const char *); +void _exits(const char *); +int notify (void(*f)(void *, char *)); +int create(char *, int, int); +int errstr(char *, int); diff --git a/src/cmd/sam/err b/src/cmd/sam/err new file mode 100644 index 00000000..2a36c23b --- /dev/null +++ b/src/cmd/sam/err @@ -0,0 +1,39 @@ +address.c: In function `filematch': +address.c:159: warning: passing arg 1 of `bufreset' from incompatible pointer type +address.c:160: warning: passing arg 1 of `bufinsert' from incompatible pointer type +file.c: In function `mergeextend': +file.c:117: warning: passing arg 1 of `bufread' from incompatible pointer type +file.c: In function `fileinsert': +file.c:275: warning: passing arg 1 of `bufinsert' from incompatible pointer type +file.c: In function `filedelete': +file.c:301: warning: passing arg 1 of `bufdelete' from incompatible pointer type +file.c: In function `fileundelete': +file.c:324: warning: passing arg 1 of `bufread' from incompatible pointer type +file.c: In function `filereadc': +file.c:339: warning: passing arg 1 of `bufread' from incompatible pointer type +file.c: In function `fileload': +file.c:405: warning: passing arg 1 of `bufload' from incompatible pointer type +file.c: In function `fileundo': +file.c:528: warning: passing arg 1 of `bufdelete' from incompatible pointer type +file.c:546: warning: passing arg 1 of `bufinsert' from incompatible pointer type +file.c: In function `fileclose': +file.c:604: warning: passing arg 1 of `bufclose' from incompatible pointer type +io.c: In function `readio': +io.c:90: warning: passing arg 1 of `bufload' from incompatible pointer type +io.c: In function `writeio': +io.c:152: warning: passing arg 1 of `bufread' from incompatible pointer type +mesg.c: In function `inmesg': +mesg.c:248: warning: passing arg 1 of `bufread' from incompatible pointer type +mesg.c: In function `snarf': +mesg.c:568: warning: passing arg 1 of `bufread' from incompatible pointer type +mesg.c: In function `setgenstr': +mesg.c:612: warning: passing arg 1 of `bufread' from incompatible pointer type +sam.c: In function `readcmd': +sam.c:496: warning: passing arg 1 of `bufread' from incompatible pointer type +sam.c: In function `copy': +sam.c:676: warning: passing arg 1 of `bufread' from incompatible pointer type +xec.c: In function `s_cmd': +xec.c:234: warning: passing arg 1 of `bufread' from incompatible pointer type +xec.c:243: warning: passing arg 1 of `bufread' from incompatible pointer type +xec.c: In function `display': +xec.c:401: warning: passing arg 1 of `bufread' from incompatible pointer type diff --git a/src/cmd/sam/plumb.h b/src/cmd/sam/plumb.h new file mode 100644 index 00000000..d376acd0 --- /dev/null +++ b/src/cmd/sam/plumb.h @@ -0,0 +1,17 @@ +typedef struct Plumbmsg Plumbmsg; + +struct Plumbmsg { + char *src; + char *dst; + char *wdir; + char *type; + char *attr; + char *data; + int ndata; +}; + +char *plumbunpackattr(char*); +char *plumbpack(Plumbmsg *, int *); +int plumbfree(Plumbmsg *); +char *cleanname(char*); + diff --git a/src/cmd/sam/string.c b/src/cmd/sam/string.c new file mode 100644 index 00000000..9a4b9a71 --- /dev/null +++ b/src/cmd/sam/string.c @@ -0,0 +1,193 @@ +#include "sam.h" + +#define MINSIZE 16 /* minimum number of chars allocated */ +#define MAXSIZE 256 /* maximum number of chars for an empty string */ + + +void +Strinit(String *p) +{ + p->s = emalloc(MINSIZE*RUNESIZE); + p->n = 0; + p->size = MINSIZE; +} + +void +Strinit0(String *p) +{ + p->s = emalloc(MINSIZE*RUNESIZE); + p->s[0] = 0; + p->n = 1; + p->size = MINSIZE; +} + +void +Strclose(String *p) +{ + free(p->s); +} + +void +Strzero(String *p) +{ + if(p->size > MAXSIZE){ + p->s = erealloc(p->s, RUNESIZE*MAXSIZE); /* throw away the garbage */ + p->size = MAXSIZE; + } + p->n = 0; +} + +int +Strlen(Rune *r) +{ + Rune *s; + + for(s=r; *s; s++) + ; + return s-r; +} + +void +Strdupl(String *p, Rune *s) /* copies the null */ +{ + p->n = Strlen(s)+1; + Strinsure(p, p->n); + memmove(p->s, s, p->n*RUNESIZE); +} + +void +Strduplstr(String *p, String *q) /* will copy the null if there's one there */ +{ + Strinsure(p, q->n); + p->n = q->n; + memmove(p->s, q->s, q->n*RUNESIZE); +} + +void +Straddc(String *p, int c) +{ + Strinsure(p, p->n+1); + p->s[p->n++] = c; +} + +void +Strinsure(String *p, ulong n) +{ + if(n > STRSIZE) + error(Etoolong); + if(p->size < n){ /* p needs to grow */ + n += 100; + p->s = erealloc(p->s, n*RUNESIZE); + p->size = n; + } +} + +void +Strinsert(String *p, String *q, Posn p0) +{ + Strinsure(p, p->n+q->n); + memmove(p->s+p0+q->n, p->s+p0, (p->n-p0)*RUNESIZE); + memmove(p->s+p0, q->s, q->n*RUNESIZE); + p->n += q->n; +} + +void +Strdelete(String *p, Posn p1, Posn p2) +{ + memmove(p->s+p1, p->s+p2, (p->n-p2)*RUNESIZE); + p->n -= p2-p1; +} + +int +Strcmp(String *a, String *b) +{ + int i, c; + + for(i=0; in && in; i++) + if(c = (a->s[i] - b->s[i])) /* assign = */ + return c; + /* damn NULs confuse everything */ + i = a->n - b->n; + if(i == 1){ + if(a->s[a->n-1] == 0) + return 0; + }else if(i == -1){ + if(b->s[b->n-1] == 0) + return 0; + } + return i; +} + +int +Strispre(String *a, String *b) +{ + int i; + + for(i=0; in && in; i++){ + if(a->s[i] - b->s[i]){ /* assign = */ + if(a->s[i] == 0) + return 1; + return 0; + } + } + return i == a->n; +} + +char* +Strtoc(String *s) +{ + int i; + char *c, *d; + Rune *r; + c = emalloc(s->n*UTFmax + 1); /* worst case UTFmax bytes per rune, plus NUL */ + d = c; + r = s->s; + for(i=0; in; i++) + d += runetochar(d, r++); + if(d==c || d[-1]!=0) + *d = 0; + return c; + +} + +/* + * Build very temporary String from Rune* + */ +String* +tmprstr(Rune *r, int n) +{ + static String p; + + p.s = r; + p.n = n; + p.size = n; + return &p; +} + +/* + * Convert null-terminated char* into String + */ +String* +tmpcstr(char *s) +{ + String *p; + Rune *r; + int i, n; + + n = utflen(s); /* don't include NUL */ + p = emalloc(sizeof(String)); + r = emalloc(n*RUNESIZE); + p->s = r; + for(i=0; in = n; + p->size = n; + return p; +} + +void +freetmpstr(String *s) +{ + free(s->s); + free(s); +} diff --git a/src/cmd/sam/sys.c b/src/cmd/sam/sys.c new file mode 100644 index 00000000..db54d28d --- /dev/null +++ b/src/cmd/sam/sys.c @@ -0,0 +1,60 @@ +#include "sam.h" + +static int inerror=FALSE; + +/* + * A reasonable interface to the system calls + */ + +void +resetsys(void) +{ + inerror = FALSE; +} + +void +syserror(char *a) +{ + char buf[ERRMAX]; + + if(!inerror){ + inerror=TRUE; + errstr(buf, sizeof buf); + dprint("%s: ", a); + error_s(Eio, buf); + } +} + +int +Read(int f, void *a, int n) +{ + char buf[ERRMAX]; + + if(read(f, (char *)a, n)!=n) { + if (lastfile) + lastfile->rescuing = 1; + errstr(buf, sizeof buf); + if (downloaded) + fprint(2, "read error: %s\n", buf); + rescue(); + exits("read"); + } + return n; +} + +int +Write(int f, void *a, int n) +{ + int m; + + if((m=write(f, (char *)a, n))!=n) + syserror("write"); + return m; +} + +void +Seek(int f, long n, int w) +{ + if(seek(f, n, w)==-1) + syserror("seek"); +} diff --git a/src/cmd/sam/util.c b/src/cmd/sam/util.c new file mode 100644 index 00000000..b2599689 --- /dev/null +++ b/src/cmd/sam/util.c @@ -0,0 +1,54 @@ +#include "sam.h" + +void +cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls) +{ + uchar *q; + Rune *s; + int j, w; + + /* + * Always guaranteed that n bytes may be interpreted + * without worrying about partial runes. This may mean + * reading up to UTFmax-1 more bytes than n; the caller + * knows this. If n is a firm limit, the caller should + * set p[n] = 0. + */ + q = (uchar*)p; + s = r; + for(j=0; j +#include +#include + +Image* +allocimagemix(Display *d, u32int color1, u32int color3) +{ + Image *t, *b; + static Image *qmask; + + if(qmask == nil) + qmask = allocimage(d, Rect(0,0,1,1), GREY8, 1, 0x3F3F3FFF); + + if(d->screenimage->depth <= 8){ /* create a 2×2 texture */ + t = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 0, color1); + if(t == nil) + return nil; + + b = allocimage(d, Rect(0,0,2,2), d->screenimage->chan, 1, color3); + if(b == nil){ + freeimage(t); + return nil; + } + + draw(b, Rect(0,0,1,1), t, nil, ZP); + freeimage(t); + return b; + }else{ /* use a solid color, blended using alpha */ + t = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 1, color1); + if(t == nil) + return nil; + + b = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 1, color3); + if(b == nil){ + freeimage(t); + return nil; + } + + draw(b, b->r, t, qmask, ZP); + freeimage(t); + return b; + } +} diff --git a/src/libdraw/bezier.c b/src/libdraw/bezier.c new file mode 100644 index 00000000..dca61bc0 --- /dev/null +++ b/src/libdraw/bezier.c @@ -0,0 +1,244 @@ +#include +#include +#include + +#define PINC 32 /* realloc granularity */ + +typedef struct Plist Plist; +struct Plist +{ + Point *p; + int np; /* -1 if malloc/realloc failed */ +}; + +static void +appendpt(Plist *l, Point p) +{ + if(l->np == -1) + return; + if(l->np == 0) + l->p = malloc(PINC*sizeof(Point)); + else if(l->np%PINC == 0) + l->p = realloc(l->p, (l->np+PINC)*sizeof(Point)); + if(l->p == 0){ + l->np = -1; + return; + } + l->p[l->np++] = p; +} + +static int +normsq(Point p) +{ + return p.x*p.x+p.y*p.y; +} + +static int +psdist(Point p, Point a, Point b) +{ + int num, den; + + p = subpt(p, a); + b = subpt(b, a); + num = p.x*b.x + p.y*b.y; + if(num <= 0) + return normsq(p); + den = normsq(b); + if(num >= den) + return normsq(subpt(b, p)); + return normsq(subpt(divpt(mulpt(b, num), den), p)); +} + +/* + * Convert cubic Bezier curve control points to polyline + * vertices. Leaves the last vertex off, so you can continue + * with another curve. + */ +static void +bpts1(Plist *l, Point p0, Point p1, Point p2, Point p3, int scale) +{ + Point p01, p12, p23, p012, p123, p0123; + Point tp0, tp1, tp2, tp3; + tp0=divpt(p0, scale); + tp1=divpt(p1, scale); + tp2=divpt(p2, scale); + tp3=divpt(p3, scale); + if(psdist(tp1, tp0, tp3)<=1 && psdist(tp2, tp0, tp3)<=1){ + appendpt(l, tp0); + appendpt(l, tp1); + appendpt(l, tp2); + } + else{ + /* + * if scale factor is getting too big for comfort, + * rescale now & concede the rounding error + */ + if(scale>(1<<12)){ + p0=tp0; + p1=tp1; + p2=tp2; + p3=tp3; + scale=1; + } + p01=addpt(p0, p1); + p12=addpt(p1, p2); + p23=addpt(p2, p3); + p012=addpt(p01, p12); + p123=addpt(p12, p23); + p0123=addpt(p012, p123); + bpts1(l, mulpt(p0, 8), mulpt(p01, 4), mulpt(p012, 2), p0123, scale*8); + bpts1(l, p0123, mulpt(p123, 2), mulpt(p23, 4), mulpt(p3, 8), scale*8); + } +} + +static void +bpts(Plist *l, Point p0, Point p1, Point p2, Point p3) +{ + bpts1(l, p0, p1, p2, p3, 1); +} + +static void +bezierpts(Plist *l, Point p0, Point p1, Point p2, Point p3) +{ + bpts(l, p0, p1, p2, p3); + appendpt(l, p3); +} + +static void +_bezsplinepts(Plist *l, Point *pt, int npt) +{ + Point *p, *ep; + Point a, b, c, d; + int periodic; + + if(npt<3) + return; + ep = &pt[npt-3]; + periodic = eqpt(pt[0], ep[2]); + if(periodic){ + a = divpt(addpt(ep[1], pt[0]), 2); + b = divpt(addpt(ep[1], mulpt(pt[0], 5)), 6); + c = divpt(addpt(mulpt(pt[0], 5), pt[1]), 6); + d = divpt(addpt(pt[0], pt[1]), 2); + bpts(l, a, b, c, d); + } + for(p=pt; p<=ep; p++){ + if(p==pt && !periodic){ + a = p[0]; + b = divpt(addpt(p[0], mulpt(p[1], 2)), 3); + } + else{ + a = divpt(addpt(p[0], p[1]), 2); + b = divpt(addpt(p[0], mulpt(p[1], 5)), 6); + } + if(p==ep && !periodic){ + c = divpt(addpt(mulpt(p[1], 2), p[2]), 3); + d = p[2]; + } + else{ + c = divpt(addpt(mulpt(p[1], 5), p[2]), 6); + d = divpt(addpt(p[1], p[2]), 2); + } + bpts(l, a, b, c, d); + } + appendpt(l, d); +} + +int +bezsplinepts(Point *pt, int npt, Point **pp) +{ + Plist l; + l.np = 0; + l.p = nil; + _bezsplinepts(&l, pt, npt); + *pp = l.p; + return l.np; +} + +int +bezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp) +{ + return bezierop(dst, p0, p1, p2, p3, end0, end1, radius, src, sp, SoverD); +} + +int +bezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp, Drawop op) +{ + Plist l; + + l.np = 0; + bezierpts(&l, p0, p1, p2, p3); + if(l.np == -1) + return 0; + if(l.np != 0){ + polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, p0), l.p[0]), op); + free(l.p); + } + return 1; +} + +int +bezspline(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp) +{ + return bezsplineop(dst, pt, npt, end0, end1, radius, src, sp, SoverD); +} + +int +bezsplineop(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp, Drawop op) +{ + Plist l; + + l.np = 0; + _bezsplinepts(&l, pt, npt); + if(l.np==-1) + return 0; + if(l.np != 0){ + polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, pt[0]), l.p[0]), op); + free(l.p); + } + return 1; +} + +int +fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp) +{ + return fillbezierop(dst, p0, p1, p2, p3, w, src, sp, SoverD); +} + +int +fillbezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp, Drawop op) +{ + Plist l; + + l.np = 0; + bezierpts(&l, p0, p1, p2, p3); + if(l.np == -1) + return 0; + if(l.np != 0){ + fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, p0), l.p[0]), op); + free(l.p); + } + return 1; +} + +int +fillbezspline(Image *dst, Point *pt, int npt, int w, Image *src, Point sp) +{ + return fillbezsplineop(dst, pt, npt, w, src, sp, SoverD); +} + +int +fillbezsplineop(Image *dst, Point *pt, int npt, int w, Image *src, Point sp, Drawop op) +{ + Plist l; + + l.np = 0; + _bezsplinepts(&l, pt, npt); + if(l.np == -1) + return 0; + if(l.np > 0){ + fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, pt[0]), l.p[0]), op); + free(l.p); + } + return 1; +} diff --git a/src/libdraw/border.c b/src/libdraw/border.c new file mode 100644 index 00000000..22637dfa --- /dev/null +++ b/src/libdraw/border.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void +border(Image *im, Rectangle r, int i, Image *color, Point sp) +{ + if(i < 0){ + r = insetrect(r, i); + sp = addpt(sp, Pt(i,i)); + i = -i; + } + draw(im, Rect(r.min.x, r.min.y, r.max.x, r.min.y+i), + color, nil, sp); + draw(im, Rect(r.min.x, r.max.y-i, r.max.x, r.max.y), + color, nil, Pt(sp.x, sp.y+Dy(r)-i)); + draw(im, Rect(r.min.x, r.min.y+i, r.min.x+i, r.max.y-i), + color, nil, Pt(sp.x, sp.y+i)); + draw(im, Rect(r.max.x-i, r.min.y+i, r.max.x, r.max.y-i), + color, nil, Pt(sp.x+Dx(r)-i, sp.y+i)); +} diff --git a/src/libdraw/cloadimage.c b/src/libdraw/cloadimage.c new file mode 100644 index 00000000..eb30466c --- /dev/null +++ b/src/libdraw/cloadimage.c @@ -0,0 +1,49 @@ +#include +#include +#include + +int +cloadimage(Image *i, Rectangle r, uchar *data, int ndata) +{ + int m, nb, miny, maxy, ncblock; + uchar *a; + + if(!rectinrect(r, i->r)){ + werrstr("cloadimage: bad rectangle"); + return -1; + } + + miny = r.min.y; + m = 0; + ncblock = _compblocksize(r, i->depth); + while(miny != r.max.y){ + maxy = atoi((char*)data+0*12); + nb = atoi((char*)data+1*12); + if(maxy<=miny || r.max.yndata){ + werrstr("creadimage: bad count %d", nb); + return -1; + } + a = bufimage(i->display, 21+nb); + if(a == nil) + return -1; + a[0] = 'Y'; + BPLONG(a+1, i->id); + BPLONG(a+5, r.min.x); + BPLONG(a+9, miny); + BPLONG(a+13, r.max.x); + BPLONG(a+17, maxy); + memmove(a+21, data, nb); + miny = maxy; + data += nb; + ndata += nb; + m += nb; + } + return m; +} diff --git a/src/libdraw/computil.c b/src/libdraw/computil.c new file mode 100644 index 00000000..30a3d11e --- /dev/null +++ b/src/libdraw/computil.c @@ -0,0 +1,38 @@ +#include +#include +#include + +/* + * compressed data are seuences of byte codes. + * if the first byte b has the 0x80 bit set, the next (b^0x80)+1 bytes + * are data. otherwise, it's two bytes specifying a previous string to repeat. + */ +void +_twiddlecompressed(uchar *buf, int n) +{ + uchar *ebuf; + int j, k, c; + + ebuf = buf+n; + while(buf < ebuf){ + c = *buf++; + if(c >= 128){ + k = c-128+1; + for(j=0; j +#include +#include + +void +drawsetdebug(int v) +{ + uchar *a; + a = bufimage(display, 1+1); + if(a == 0){ + fprint(2, "drawsetdebug: %r\n"); + return; + } + a[0] = 'D'; + a[1] = v; +} diff --git a/src/libdraw/defont.c b/src/libdraw/defont.c new file mode 100644 index 00000000..b0c85e1d --- /dev/null +++ b/src/libdraw/defont.c @@ -0,0 +1,402 @@ +#include +#include +#include + +/* + * lucm/latin1.9, in uncompressed form + */ +uchar +defontdata[] = +{ +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x32,0x33,0x30,0x34,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x35,0x20,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x06,0x06,0x03,0x42,0x40,0x00,0x00,0x00,0x18,0x03,0x03, +0x02,0x43,0x00,0x60,0x60,0x48,0x00,0x0d,0x0c,0x01,0x81,0x80,0xd0,0x90,0x00,0x00, +0x18,0x01,0x81,0x81,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x7f,0x9c,0x1c, +0x0e,0x07,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x70, +0x38,0x1c,0x0e,0x04,0x81,0xc1,0xc0,0x70,0x00,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x80,0xc0,0x63,0xe3, +0xf1,0xf8,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f,0xff,0xff,0x1f,0x8f, +0xc7,0xe3,0xf1,0xfb,0x7e,0x3e,0x3f,0x8f,0xff,0xe3,0xe3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x0c,0x18,0x09,0x05,0x82,0x40,0xc0,0x00,0x00,0x06,0x0c,0x04, +0x82,0x40,0xc1,0x80,0x90,0x48,0x00,0x16,0x03,0x06,0x02,0x41,0x60,0x90,0x00,0x00, +0x06,0x06,0x02,0x41,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7f,0xa0,0x10, +0x08,0x04,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x48, +0x24,0x12,0x09,0x06,0x82,0x01,0x00,0x90,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x04,0x80,0x00,0x40,0x00,0x00,0x38,0x06,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0xc6,0x01,0xf0,0x00,0x00,0x0c,0x00,0x18,0x00,0x00,0x30,0x00,0x3c, +0x00,0x60,0x06,0x01,0x8c,0x07,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0xc3,0xc0,0x01,0x54,0x9c,0xc0,0x5f,0xef, +0xf7,0xfb,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0x7f,0xff,0xff,0x6f,0xb7, +0xdb,0xed,0xf6,0xf9,0x7d,0xfe,0xff,0x6f,0xff,0xdf,0xef,0xff,0xff,0xff,0xff,0xff, +0xff,0x00,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x30,0x06,0x06,0x06,0x82,0x80,0xc0,0x00, +0x00,0x18,0x03,0x03,0x02,0x41,0x80,0x30,0x30,0x24,0x76,0x0d,0x0c,0x00,0xc0,0xc0, +0xd0,0x50,0x00,0x00,0x18,0x01,0x81,0x81,0x40,0x30,0x00,0x28,0x0f,0x7f,0xbc,0x1c, +0x0e,0x07,0x03,0xc0,0x10,0x70,0x24,0x10,0x09,0x07,0x03,0x80,0xe0,0x70,0x90,0x48, +0x24,0x12,0x09,0x05,0x81,0x81,0xc0,0x80,0x70,0x18,0x1c,0x07,0x01,0xc1,0xc0,0x90, +0x00,0x0c,0x04,0x84,0x83,0xe1,0xc0,0xe0,0x38,0x0c,0x0c,0x02,0x00,0x00,0x00,0x00, +0x00,0x06,0x1c,0x06,0x0f,0x87,0xc0,0x63,0xf8,0x78,0xfe,0x3e,0x0e,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0x1c,0x0c,0x1f,0x03,0xc7,0xc3,0xf1,0xf8,0x3c,0x63,0x3f,0x0f, +0x8c,0x66,0x06,0x19,0x84,0x78,0x7e,0x1e,0x1f,0x07,0xcf,0xf3,0x1b,0x0d,0x86,0x63, +0x61,0x9f,0xc6,0x06,0x00,0x30,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x30,0x00,0x60, +0x00,0x60,0x06,0x01,0x8c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x00,0xaa,0xb6,0xc0,0x43,0xe3, +0xf1,0xf8,0xfc,0x3f,0xef,0x8f,0xdb,0xef,0xf6,0xf8,0xfb,0xff,0x1f,0x8f,0x6f,0xb7, +0xdb,0xed,0xf6,0xfa,0x7e,0x7e,0x3f,0x7f,0x8f,0xe7,0xe3,0xf8,0xfe,0x3e,0x3f,0x6f, +0x00,0x00,0x01,0x01,0xc8,0x0b,0x0c,0x30,0x7c,0x14,0x0f,0x0f,0x00,0x00,0x00,0x00, +0x78,0x00,0x1c,0x00,0x0f,0x07,0x81,0x80,0x00,0x7c,0x00,0x00,0x1c,0x0f,0x80,0x04, +0x42,0x23,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x3c,0x3c,0x3f,0x1f,0x8f, +0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x30,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0x3d, +0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x0c,0x18,0x09,0x0b,0x02,0x81,0x20,0x00, +0x00,0x06,0x0c,0x04,0x82,0x40,0x60,0xc0,0x48,0x24,0x18,0x16,0x03,0x03,0x01,0x21, +0x60,0x50,0x00,0x00,0x06,0x06,0x02,0x41,0x40,0xc1,0x80,0x28,0x87,0x7f,0x84,0x10, +0x08,0x04,0x02,0x40,0x38,0x48,0x24,0x10,0x09,0x04,0x04,0x81,0x00,0x80,0x90,0x48, +0x24,0x12,0x09,0x04,0x80,0x41,0x00,0x80,0x40,0x04,0x10,0x04,0x02,0x01,0x20,0x90, +0x00,0x0c,0x04,0x84,0x86,0x53,0x65,0xb0,0x08,0x18,0x06,0x0a,0x80,0x00,0x00,0x00, +0x00,0x0c,0x36,0x0e,0x19,0xcc,0xe0,0xe3,0xf8,0xcc,0xfe,0x63,0x1b,0x00,0x00,0x00, +0x00,0x00,0x00,0xc6,0x62,0x0c,0x19,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x01, +0x8c,0xc6,0x06,0x19,0xc4,0xcc,0x63,0x33,0x19,0x8c,0x61,0x83,0x1b,0x0d,0x86,0x63, +0x61,0x80,0xc6,0x03,0x00,0x30,0x30,0x00,0x1c,0x00,0x18,0x00,0x00,0x30,0x00,0x60, +0x00,0x60,0x00,0x00,0x0c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x01,0x54,0x86,0xc0,0x7b,0xef, +0xf7,0xfb,0xfd,0xbf,0xc7,0xb7,0xdb,0xef,0xf6,0xfb,0xfb,0x7e,0xff,0x7f,0x6f,0xb7, +0xdb,0xed,0xf6,0xfb,0x7f,0xbe,0xff,0x7f,0xbf,0xfb,0xef,0xfb,0xfd,0xfe,0xdf,0x6f, +0xff,0x00,0x07,0x83,0x24,0x13,0x0c,0x30,0xc6,0x00,0x10,0x81,0x80,0x00,0x00,0x00, +0x84,0x00,0x22,0x00,0x01,0x80,0xc0,0x00,0x00,0xf4,0x00,0x00,0x2c,0x18,0xc0,0x0c, +0x46,0x20,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x70,0x66,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x38,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66, +0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0xff,0x7f,0xb8,0x1c, +0x0e,0x07,0x02,0x40,0x7c,0x70,0x3c,0x10,0x09,0x07,0x04,0x00,0xc0,0x60,0xe0,0x70, +0x38,0x1c,0x0e,0x04,0x83,0x81,0xc0,0x70,0x70,0x38,0x1c,0x07,0x02,0xc1,0xc0,0x90, +0x00,0x0c,0x00,0x04,0x86,0x43,0x69,0xb0,0x30,0x18,0x06,0x07,0x01,0x00,0x00,0x00, +0x00,0x0c,0x63,0x16,0x00,0xc0,0x61,0x62,0x01,0x80,0x06,0x63,0x31,0x80,0x00,0x00, +0x60,0x00,0xc0,0x06,0x43,0x16,0x19,0x8c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01, +0x8c,0x86,0x07,0x39,0xc5,0x86,0x63,0x61,0x99,0x8c,0x01,0x83,0x1b,0x0d,0xb6,0x63, +0x31,0x01,0x86,0x03,0x00,0x30,0x30,0x00,0x1c,0x3e,0x1b,0x03,0xc1,0xf0,0xf0,0x60, +0x3e,0x6e,0x3e,0x0f,0x8c,0x60,0xc5,0xb1,0xb8,0x38,0x6c,0x0f,0x8c,0xc7,0xc1,0x83, +0x19,0x8d,0x82,0x63,0x31,0x9f,0xc1,0x80,0xc0,0xc0,0x00,0xaa,0x86,0xc0,0x47,0xe3, +0xf1,0xf8,0xfd,0xbf,0x83,0x8f,0xc3,0xef,0xf6,0xf8,0xfc,0xff,0x3f,0x9f,0x1f,0x8f, +0xc7,0xe3,0xf1,0xfb,0x7c,0x7e,0x3f,0x8f,0x8f,0xc7,0xe3,0xf8,0xfd,0x3e,0x3f,0x6f, +0x00,0x0c,0x0d,0x43,0x03,0xe1,0x88,0x30,0xc0,0x00,0x27,0x41,0x80,0x00,0x00,0x01, +0x72,0x00,0x22,0x04,0x01,0x80,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xc0,0x04, +0x82,0x43,0x20,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x38,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x00,0xc7, +0x31,0x98,0xcc,0x66,0x33,0x11,0xf8,0xc8,0x7c,0x3e,0x1f,0x0f,0x87,0xc3,0xe1,0xd8, +0x3c,0x1e,0x0f,0x07,0x83,0xc7,0xc3,0xe1,0xf0,0xf8,0x06,0x37,0x07,0x03,0x81,0xc0, +0xe0,0x70,0x10,0x1d,0x31,0x98,0xcc,0x66,0x33,0x19,0xb0,0xc6,0x8f,0x7f,0x87,0x03, +0x81,0x80,0x90,0x30,0x6c,0x48,0x24,0x10,0x06,0x04,0x04,0x80,0x20,0x10,0x10,0x0e, +0x07,0x03,0x81,0xc0,0x60,0x88,0x38,0x0c,0x40,0x09,0x03,0x84,0x02,0x41,0x40,0x90, +0x00,0x0c,0x00,0x1f,0xe7,0x41,0xd1,0xa0,0x00,0x30,0x03,0x0a,0x81,0x00,0x00,0x00, +0x00,0x18,0x63,0x06,0x00,0xc0,0xc2,0x62,0x01,0xb0,0x0c,0x72,0x31,0x86,0x03,0x00, +0xc0,0x00,0x60,0x06,0x8f,0x16,0x19,0x0c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01, +0x8d,0x06,0x07,0x39,0x65,0x86,0x63,0x61,0x99,0x0e,0x01,0x83,0x19,0x89,0xb6,0x32, +0x33,0x03,0x06,0x01,0x80,0x30,0x78,0x00,0x00,0x03,0x1d,0x86,0x23,0x31,0x99,0xfc, +0x66,0x77,0x06,0x01,0x8c,0x40,0xc6,0xd9,0xdc,0x6c,0x76,0x19,0x8d,0xcc,0x27,0xf3, +0x19,0x8d,0x82,0x63,0x31,0x80,0xc0,0x80,0xc0,0x80,0x01,0x54,0x8c,0xc0,0x78,0xfc, +0x7e,0x7f,0x6f,0xcf,0x93,0xb7,0xdb,0xef,0xf9,0xfb,0xff,0xff,0xdf,0xef,0xef,0xf1, +0xf8,0xfc,0x7e,0x3f,0x9f,0x77,0xc7,0xf3,0xbf,0xf6,0xfc,0x7b,0xfd,0xbe,0xbf,0x6f, +0xff,0x0c,0x19,0x03,0x03,0x61,0x98,0x30,0x78,0x00,0x28,0x4f,0x83,0x30,0x00,0x01, +0x4a,0x00,0x1c,0x04,0x03,0x03,0x80,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xd9,0x84, +0x82,0x40,0xa0,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x64,0xcb, +0x31,0x98,0xcc,0x66,0x33,0x31,0x8c,0xd8,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c, +0x62,0x33,0x19,0x8c,0xc6,0x60,0xc0,0x60,0x30,0x18,0x1e,0x3b,0x8d,0x86,0xc3,0x61, +0xb0,0xd8,0x10,0x36,0x31,0x98,0xcc,0x66,0x33,0x19,0xd8,0xc6,0x0f,0x7f,0x82,0x01, +0x02,0x40,0xd0,0x40,0x6c,0x70,0x24,0x1c,0x06,0x04,0x03,0x01,0xc0,0xe0,0x10,0x12, +0x09,0x04,0x82,0x40,0x90,0x50,0x10,0x12,0x70,0x09,0x04,0x04,0x01,0xc1,0x20,0x60, +0x00,0x0c,0x00,0x04,0x83,0xc0,0x20,0xcc,0x00,0x30,0x03,0x02,0x01,0x00,0x00,0x00, +0x00,0x18,0x63,0x06,0x01,0x83,0x84,0x63,0xf1,0xd8,0x18,0x3c,0x31,0x86,0x03,0x01, +0x83,0xf8,0x30,0x1c,0x9b,0x33,0x1e,0x0c,0x06,0x33,0xe1,0x80,0xc0,0x7f,0x0c,0x01, +0x8f,0x06,0x07,0x79,0x65,0x86,0x66,0x61,0x9e,0x07,0x81,0x83,0x19,0x89,0xb6,0x1c, +0x1a,0x03,0x06,0x01,0x80,0x30,0x48,0x00,0x00,0x03,0x18,0xcc,0x06,0x33,0x18,0x60, +0xc6,0x63,0x06,0x01,0x8c,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8e,0x4c,0x01,0x83, +0x19,0x8d,0x92,0x32,0x31,0x81,0x87,0x00,0xc0,0x70,0xe4,0xaa,0x98,0xc0,0x7d,0xfe, +0xfd,0xbf,0x2f,0xbf,0x93,0x8f,0xdb,0xe3,0xf9,0xfb,0xff,0x1e,0x3f,0x1f,0xef,0xed, +0xf6,0xfb,0x7d,0xbf,0x6f,0xaf,0xef,0xed,0x8f,0xf6,0xfb,0xfb,0xfe,0x3e,0xdf,0x9f, +0x00,0x00,0x19,0x0f,0xc6,0x30,0xd0,0x00,0xcc,0x00,0x28,0x59,0x86,0x67,0xf0,0x01, +0x72,0x00,0x00,0x3f,0x86,0x00,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xcc,0xc5, +0x32,0x83,0x4c,0x00,0x66,0x33,0x19,0x8c,0xc6,0x63,0x31,0xbc,0xc0,0x3e,0x1f,0x0f, +0x87,0xc1,0x80,0xc0,0x60,0x30,0xfb,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xcb, +0x31,0x98,0xcc,0x66,0x31,0xa1,0x8c,0xcc,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c, +0xc0,0x63,0x31,0x98,0xcc,0x60,0xc0,0x60,0x30,0x18,0x37,0x31,0x98,0xcc,0x66,0x33, +0x19,0x8c,0x00,0x67,0x31,0x98,0xcc,0x66,0x33,0x19,0x8c,0xc6,0x1f,0x7f,0x82,0x01, +0x02,0x40,0xb0,0x40,0x6c,0x07,0x03,0x83,0x80,0xe0,0xe0,0x00,0x18,0x0e,0x10,0x10, +0x08,0x04,0x02,0x00,0xf0,0x20,0x10,0x1e,0x08,0x89,0x03,0x00,0xe0,0x38,0x1c,0x0e, +0x00,0x0c,0x00,0x04,0x81,0xe0,0x41,0x6c,0x00,0x30,0x03,0x00,0x0f,0xe0,0x03,0xf8, +0x00,0x30,0x63,0x06,0x03,0x00,0xc7,0xf0,0x39,0x8c,0x30,0x3e,0x1b,0x80,0x00,0x03, +0x00,0x00,0x18,0x30,0x9b,0x23,0x19,0x0c,0x06,0x33,0x01,0xf8,0xc6,0x63,0x0c,0x01, +0x8d,0x86,0x05,0xd9,0x35,0x86,0x7c,0x61,0x9b,0x01,0xc1,0x83,0x19,0x99,0xb4,0x1c, +0x0c,0x06,0x06,0x00,0xc0,0x30,0xcc,0x00,0x00,0x3f,0x18,0xcc,0x06,0x33,0xf8,0x60, +0xc6,0x63,0x06,0x01,0x8f,0x00,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x0f,0x81,0x83, +0x18,0xd9,0xba,0x1c,0x1b,0x03,0x00,0x80,0xc0,0x81,0x75,0x54,0x98,0xc0,0x7d,0xfe, +0xfd,0xbf,0x4f,0xbf,0x93,0xf8,0xfc,0x7c,0x7f,0x1f,0x1f,0x6f,0xe7,0xf1,0xef,0xef, +0xf7,0xfb,0xfd,0xff,0x0f,0xdf,0xef,0xe1,0xf7,0x76,0xfc,0xff,0x1f,0xc7,0xe3,0xf1, +0xff,0x08,0x19,0x03,0x06,0x31,0xf8,0x00,0xc6,0x00,0x28,0x5b,0x8c,0xc0,0x11,0xf1, +0x4a,0x00,0x00,0x04,0x0c,0x00,0xc0,0x03,0x18,0x74,0x38,0x00,0x0c,0x18,0xc6,0x65, +0x52,0xb8,0x54,0x18,0x46,0x23,0x11,0x88,0xc4,0x62,0x31,0x30,0xc0,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x10,0xd3, +0x31,0x98,0xcc,0x66,0x30,0xc1,0x8c,0xc6,0x7e,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xfc, +0xc0,0x7f,0x3f,0x9f,0xcf,0xe0,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, +0x19,0x8c,0xfe,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x0e,0x7f,0x82,0x01, +0x01,0x80,0x90,0x30,0xc6,0x08,0x01,0x02,0x00,0x40,0x80,0xe0,0x24,0x04,0x1c,0x10, +0x08,0x04,0x02,0x00,0x90,0x20,0x10,0x12,0x0d,0x86,0x00,0x81,0x00,0x40,0x20,0x10, +0x00,0x04,0x00,0x1f,0xe1,0x70,0xbb,0x28,0x00,0x30,0x03,0x00,0x01,0x00,0x00,0x00, +0x00,0x30,0x63,0x06,0x06,0x00,0x67,0xf0,0x19,0x8c,0x30,0x67,0x0d,0x80,0x00,0x01, +0x83,0xf8,0x30,0x30,0x9b,0x7f,0x19,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01, +0x8c,0xc6,0x05,0xd9,0x35,0x86,0x60,0x61,0x99,0x80,0xe1,0x83,0x18,0xd0,0xdc,0x26, +0x0c,0x0c,0x06,0x00,0xc0,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60, +0xc6,0x63,0x06,0x01,0x8d,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x03,0xe1,0x83, +0x18,0xd9,0xba,0x1c,0x1b,0x06,0x01,0x80,0xc0,0xc1,0x38,0xaa,0x80,0xc0,0x7d,0xfe, +0xfe,0x7f,0x6f,0xcf,0x39,0xf7,0xfe,0xfd,0xff,0xbf,0x7f,0x0f,0xdb,0xfb,0xe3,0xef, +0xf7,0xfb,0xfd,0xff,0x6f,0xdf,0xef,0xed,0xf2,0x79,0xff,0x7e,0xff,0xbf,0xdf,0xef, +0x00,0x0c,0x19,0x03,0x03,0x60,0x60,0x30,0x66,0x00,0x28,0x4d,0xc6,0x60,0x10,0x00, +0x84,0x00,0x00,0x04,0x0f,0x87,0x80,0x03,0x18,0x14,0x38,0x00,0x3f,0x0f,0x8c,0xc2, +0x90,0x84,0xa4,0x18,0xfe,0x7f,0x3f,0x9f,0xcf,0xe7,0xf1,0xf0,0xc0,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xd3, +0x31,0x98,0xcc,0x66,0x30,0xc1,0x98,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60, +0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, +0x19,0x8c,0x00,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x1c,0x7f,0x81,0x20, +0x90,0x38,0x18,0x0b,0x83,0x06,0x01,0x03,0x80,0x40,0xe0,0x90,0x24,0x04,0x03,0x8e, +0x86,0xc3,0x61,0x90,0x24,0x12,0x0e,0x04,0x8a,0x81,0xc7,0x70,0xc0,0x30,0x18,0x0c, +0x00,0x00,0x00,0x04,0x81,0x31,0x6f,0x30,0x00,0x18,0x06,0x00,0x01,0x00,0x00,0x00, +0x00,0x60,0x63,0x06,0x0c,0x00,0x60,0x60,0x19,0x8c,0x60,0x63,0x01,0x80,0x00,0x00, +0xc0,0x00,0x60,0x00,0x4d,0xe1,0x99,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01, +0x8c,0xc6,0x04,0x99,0x1d,0x86,0x60,0x61,0x99,0x80,0x61,0x83,0x18,0xd0,0xdc,0x63, +0x0c,0x0c,0x06,0x00,0x60,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60, +0x6e,0x63,0x06,0x01,0x8c,0xc0,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x00,0x61,0x83, +0x18,0xd0,0xcc,0x26,0x0e,0x0c,0x03,0x00,0xc0,0x60,0x01,0x54,0x98,0xc0,0x7e,0xdf, +0x6f,0xc7,0xe7,0xf4,0x7c,0xf9,0xfe,0xfc,0x7f,0xbf,0x1f,0x5f,0xdb,0xfb,0xfc,0x71, +0x79,0x3c,0x9e,0x6f,0xdb,0xed,0xf1,0xfb,0x75,0x7e,0x38,0x8f,0x3f,0xcf,0xe7,0xf3, +0xff,0x0c,0x0d,0x03,0x03,0xe1,0xf8,0x30,0x3c,0x00,0x27,0x40,0x03,0x30,0x00,0x00, +0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x14,0x00,0x00,0x00,0x00,0x19,0x82, +0xf8,0x98,0xbe,0x70,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0xc0,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x23,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x4c,0xe3, +0x31,0x98,0xcc,0x66,0x30,0xc1,0xf0,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60, +0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, +0x19,0x8c,0x10,0x73,0x31,0x98,0xcc,0x66,0x30,0xe1,0x8c,0x38,0x1c,0x7f,0x80,0xa0, +0x50,0x10,0x24,0x0d,0xff,0x01,0x01,0x02,0x00,0x40,0x80,0xf0,0x24,0x04,0x02,0x01, +0x81,0x20,0x10,0x30,0x28,0x1a,0x09,0x06,0x8a,0x81,0x20,0x90,0x20,0x08,0x04,0x02, +0x00,0x0c,0x00,0x04,0x85,0x32,0x6f,0xb8,0x00,0x18,0x06,0x00,0x01,0x01,0xc0,0x00, +0x70,0x60,0x36,0x06,0x1f,0xcc,0xe0,0x63,0x30,0xd8,0x60,0x63,0x33,0x06,0x03,0x00, +0x60,0x00,0xc0,0x30,0x60,0x61,0x99,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x03, +0x0c,0x66,0x04,0x19,0x1c,0xcc,0x60,0x33,0x18,0xcc,0x61,0x81,0xb0,0x60,0xcc,0x63, +0x0c,0x18,0x06,0x00,0x60,0x30,0x00,0x00,0x00,0x67,0x19,0x86,0x23,0x71,0x88,0x60, +0x36,0x63,0x06,0x01,0x8c,0x60,0xc6,0xd9,0x8c,0x6c,0x66,0x1b,0x8c,0x08,0x61,0x83, +0xb8,0x70,0xcc,0x63,0x0c,0x18,0x03,0x00,0xc0,0x60,0x00,0xaa,0x98,0xc0,0x7f,0x5f, +0xaf,0xef,0xdb,0xf2,0x00,0xfe,0xfe,0xfd,0xff,0xbf,0x7f,0x6f,0xdb,0xfb,0xfd,0xfe, +0x7e,0xdf,0xef,0xcf,0xd7,0xe5,0xf6,0xf9,0x75,0x7e,0xdf,0x6f,0xdf,0xf7,0xfb,0xfd, +0x00,0x0c,0x07,0xc6,0x04,0x10,0x60,0x30,0x06,0x00,0x10,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x3f,0x80,0x00,0x00,0x03,0xb8,0x14,0x00,0x00,0x00,0x00,0x00,0x04, +0x11,0x21,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0x66,0x30,0x18,0x0c, +0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x23,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66, +0x1b,0x0d,0x86,0xc3,0x60,0xc1,0x80,0xc6,0xce,0x67,0x33,0x99,0xcc,0xe6,0x73,0x74, +0x62,0x31,0x18,0x8c,0x46,0x20,0xc0,0x60,0x30,0x18,0x36,0x31,0x8d,0x86,0xc3,0x61, +0xb0,0xd8,0x10,0x36,0x3b,0x9d,0xce,0xe7,0x70,0xc1,0x98,0x30,0x00,0x7f,0x80,0xc0, +0x60,0x10,0x24,0x0c,0x38,0x0e,0x01,0x02,0x00,0x40,0x80,0xa0,0x18,0x0e,0x03,0x00, +0x80,0x40,0x60,0x50,0x30,0x16,0x0e,0x05,0x88,0x81,0xc0,0x81,0xc0,0x70,0x38,0x1c, +0x00,0x0c,0x00,0x04,0x83,0xe0,0x39,0xcc,0x00,0x0c,0x0c,0x00,0x00,0x01,0xc0,0x00, +0x70,0xc0,0x1c,0x06,0x1f,0xc7,0xc0,0x61,0xe0,0x70,0x60,0x3e,0x1e,0x06,0x03,0x00, +0x00,0x00,0x00,0x30,0x1e,0x61,0x9f,0x03,0xc7,0xc3,0xf1,0x80,0x3e,0x63,0x3f,0x1e, +0x0c,0x67,0xe4,0x19,0x0c,0x78,0x60,0x1e,0x18,0xc7,0xc1,0x80,0xe0,0x60,0xcc,0x63, +0x0c,0x1f,0xc6,0x00,0x30,0x30,0x00,0x00,0x00,0x3b,0x9f,0x03,0xc1,0xb0,0xf0,0x60, +0x06,0x63,0x06,0x01,0x8c,0x70,0xc6,0xd9,0x8c,0x38,0x7c,0x0d,0x8c,0x07,0xc0,0xf1, +0xd8,0x60,0xcc,0x63,0x0c,0x1f,0xc3,0x00,0xc0,0x60,0x01,0x54,0x80,0xc0,0x7f,0x3f, +0x9f,0xef,0xdb,0xf3,0xc7,0xf1,0xfe,0xfd,0xff,0xbf,0x7f,0xff,0xe7,0xf1,0xfc,0xff, +0x7f,0xbf,0x9f,0xaf,0xcf,0xe9,0xf1,0xfa,0x77,0x7e,0x3f,0x7e,0x3f,0x8f,0xc7,0xe3, +0xff,0x0c,0x01,0x0f,0xe8,0x08,0x60,0x30,0xc6,0x00,0x0f,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xd8,0x14,0x00,0x00,0x00,0x00,0x00,0x04, +0x11,0x3d,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x3c,0x3c,0x3f,0x1f,0x8f, +0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x21,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0xbc, +0x0e,0x07,0x03,0x81,0xc0,0xc1,0x80,0xcc,0x77,0x3b,0x9d,0xce,0xe7,0x73,0xb9,0x98, +0x3c,0x1e,0x0f,0x07,0x83,0xc0,0xc0,0x60,0x30,0x18,0x1c,0x31,0x87,0x03,0x81,0xc0, +0xe0,0x70,0x00,0x5c,0x1d,0x8e,0xc7,0x63,0xb0,0xc1,0xf0,0x30,0x00,0x7f,0x81,0x40, +0xa0,0x10,0x28,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x02,0x00, +0x80,0x80,0x10,0xf8,0x28,0x12,0x09,0x04,0x80,0x01,0x20,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x40,0x00, +0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0xc0,0x31,0xf0,0x01,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xcc,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x00,0x01,0xe0,0xc3,0xc0,0x00,0x00,0xff,0xc0,0x7e,0xbf, +0x5f,0xef,0xd7,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff, +0x7f,0x7f,0xef,0x07,0xd7,0xed,0xf6,0xfb,0x7f,0xfe,0xdf,0x7f,0xff,0xff,0xff,0xff, +0x00,0x0c,0x01,0x00,0x00,0x00,0x00,0x30,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x00,0x7f,0x81,0x20, +0x90,0x10,0x1c,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80, +0x81,0xe0,0x60,0x10,0x24,0x12,0x0e,0x04,0x80,0x01,0xc0,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xfe,0xdf, +0x6f,0xef,0xe3,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f, +0x7e,0x1f,0x9f,0xef,0xdb,0xed,0xf1,0xfb,0x7f,0xfe,0x3f,0x8f,0xff,0xff,0xff,0xff, +0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x20,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x32,0x35,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +0x20,0x31,0x35,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x33,0x20, +0x00,0x00,0x01,0x0c,0x00,0x09,0x09,0x00,0x01,0x0f,0x00,0x09,0x12,0x00,0x01,0x0f, +0x00,0x09,0x1b,0x00,0x01,0x0f,0x00,0x09,0x24,0x00,0x01,0x0f,0x00,0x09,0x2d,0x00, +0x01,0x0f,0x00,0x09,0x36,0x00,0x01,0x0f,0x00,0x09,0x3f,0x00,0x03,0x0d,0x00,0x09, +0x48,0x00,0x03,0x0d,0x00,0x09,0x51,0x00,0x03,0x0d,0x00,0x09,0x5a,0x00,0x03,0x0d, +0x00,0x09,0x63,0x00,0x03,0x0d,0x00,0x09,0x6c,0x00,0x03,0x0d,0x00,0x09,0x75,0x00, +0x03,0x0e,0x00,0x09,0x7e,0x00,0x03,0x0d,0x00,0x09,0x87,0x00,0x03,0x0d,0x00,0x09, +0x90,0x00,0x01,0x0f,0x00,0x09,0x99,0x00,0x01,0x0f,0x00,0x09,0xa2,0x00,0x01,0x0f, +0x00,0x09,0xab,0x00,0x01,0x0f,0x00,0x09,0xb4,0x00,0x01,0x0f,0x00,0x09,0xbd,0x00, +0x01,0x0f,0x00,0x09,0xc6,0x00,0x01,0x0f,0x00,0x09,0xcf,0x00,0x01,0x0f,0x00,0x09, +0xd8,0x00,0x01,0x0f,0x00,0x09,0xe1,0x00,0x03,0x0d,0x00,0x09,0xea,0x00,0x01,0x0f, +0x00,0x09,0xf3,0x00,0x01,0x0f,0x00,0x09,0xfc,0x00,0x03,0x0d,0x00,0x09,0x05,0x01, +0x03,0x0d,0x00,0x09,0x0e,0x01,0x03,0x0d,0x00,0x09,0x17,0x01,0x03,0x0d,0x00,0x09, +0x20,0x01,0x00,0x00,0x00,0x09,0x29,0x01,0x03,0x0d,0x00,0x09,0x32,0x01,0x02,0x05, +0x00,0x09,0x3b,0x01,0x03,0x0d,0x00,0x09,0x44,0x01,0x02,0x0e,0x00,0x09,0x4d,0x01, +0x03,0x0d,0x00,0x09,0x56,0x01,0x03,0x0d,0x00,0x09,0x5f,0x01,0x02,0x06,0x00,0x09, +0x68,0x01,0x02,0x0e,0x00,0x09,0x71,0x01,0x02,0x0e,0x00,0x09,0x7a,0x01,0x03,0x08, +0x00,0x09,0x83,0x01,0x05,0x0c,0x00,0x09,0x8c,0x01,0x0b,0x0f,0x00,0x09,0x95,0x01, +0x08,0x09,0x00,0x09,0x9e,0x01,0x0b,0x0d,0x00,0x09,0xa7,0x01,0x02,0x0e,0x00,0x09, +0xb0,0x01,0x03,0x0d,0x00,0x09,0xb9,0x01,0x03,0x0d,0x00,0x09,0xc2,0x01,0x03,0x0d, +0x00,0x09,0xcb,0x01,0x03,0x0d,0x00,0x09,0xd4,0x01,0x03,0x0d,0x00,0x09,0xdd,0x01, +0x03,0x0d,0x00,0x09,0xe6,0x01,0x03,0x0d,0x00,0x09,0xef,0x01,0x03,0x0d,0x00,0x09, +0xf8,0x01,0x03,0x0d,0x00,0x09,0x01,0x02,0x03,0x0d,0x00,0x09,0x0a,0x02,0x06,0x0d, +0x00,0x09,0x13,0x02,0x06,0x0f,0x00,0x09,0x1c,0x02,0x05,0x0c,0x00,0x09,0x25,0x02, +0x07,0x0a,0x00,0x09,0x2e,0x02,0x05,0x0c,0x00,0x09,0x37,0x02,0x03,0x0d,0x00,0x09, +0x40,0x02,0x03,0x0d,0x00,0x09,0x49,0x02,0x03,0x0d,0x00,0x09,0x52,0x02,0x03,0x0d, +0x00,0x09,0x5b,0x02,0x03,0x0d,0x00,0x09,0x64,0x02,0x03,0x0d,0x00,0x09,0x6d,0x02, +0x03,0x0d,0x00,0x09,0x76,0x02,0x03,0x0d,0x00,0x09,0x7f,0x02,0x03,0x0d,0x00,0x09, +0x88,0x02,0x03,0x0d,0x00,0x09,0x91,0x02,0x03,0x0d,0x00,0x09,0x9a,0x02,0x03,0x0d, +0x00,0x09,0xa3,0x02,0x03,0x0d,0x00,0x09,0xac,0x02,0x03,0x0d,0x00,0x09,0xb5,0x02, +0x03,0x0d,0x00,0x09,0xbe,0x02,0x03,0x0d,0x00,0x09,0xc7,0x02,0x03,0x0d,0x00,0x09, +0xd0,0x02,0x03,0x0d,0x00,0x09,0xd9,0x02,0x03,0x0f,0x00,0x09,0xe2,0x02,0x03,0x0d, +0x00,0x09,0xeb,0x02,0x03,0x0d,0x00,0x09,0xf4,0x02,0x03,0x0d,0x00,0x09,0xfd,0x02, +0x03,0x0d,0x00,0x09,0x06,0x03,0x03,0x0d,0x00,0x09,0x0f,0x03,0x03,0x0d,0x00,0x09, +0x18,0x03,0x03,0x0d,0x00,0x09,0x21,0x03,0x03,0x0d,0x00,0x09,0x2a,0x03,0x03,0x0d, +0x00,0x09,0x33,0x03,0x02,0x0e,0x00,0x09,0x3c,0x03,0x02,0x0e,0x00,0x09,0x45,0x03, +0x02,0x0e,0x00,0x09,0x4e,0x03,0x04,0x0b,0x00,0x09,0x57,0x03,0x0d,0x0e,0x00,0x09, +0x60,0x03,0x02,0x06,0x00,0x09,0x69,0x03,0x05,0x0d,0x00,0x09,0x72,0x03,0x02,0x0d, +0x00,0x09,0x7b,0x03,0x05,0x0d,0x00,0x09,0x84,0x03,0x02,0x0d,0x00,0x09,0x8d,0x03, +0x05,0x0d,0x00,0x09,0x96,0x03,0x02,0x0d,0x00,0x09,0x9f,0x03,0x05,0x0f,0x00,0x09, +0xa8,0x03,0x02,0x0d,0x00,0x09,0xb1,0x03,0x02,0x0d,0x00,0x09,0xba,0x03,0x02,0x0f, +0x00,0x09,0xc3,0x03,0x02,0x0d,0x00,0x09,0xcc,0x03,0x02,0x0d,0x00,0x09,0xd5,0x03, +0x05,0x0d,0x00,0x09,0xde,0x03,0x05,0x0d,0x00,0x09,0xe7,0x03,0x05,0x0d,0x00,0x09, +0xf0,0x03,0x05,0x0f,0x00,0x09,0xf9,0x03,0x05,0x0f,0x00,0x09,0x02,0x04,0x05,0x0d, +0x00,0x09,0x0b,0x04,0x05,0x0d,0x00,0x09,0x14,0x04,0x03,0x0d,0x00,0x09,0x1d,0x04, +0x05,0x0d,0x00,0x09,0x26,0x04,0x05,0x0d,0x00,0x09,0x2f,0x04,0x05,0x0d,0x00,0x09, +0x38,0x04,0x05,0x0d,0x00,0x09,0x41,0x04,0x05,0x0f,0x00,0x09,0x4a,0x04,0x05,0x0d, +0x00,0x09,0x53,0x04,0x02,0x0e,0x00,0x09,0x5c,0x04,0x02,0x0e,0x00,0x09,0x65,0x04, +0x02,0x0e,0x00,0x09,0x6e,0x04,0x07,0x0a,0x00,0x09,0x77,0x04,0x01,0x0d,0x00,0x09, +0x80,0x04,0x00,0x0e,0x00,0x09,0x89,0x04,0x00,0x0f,0x00,0x09,0x92,0x04,0x00,0x0f, +0x00,0x09,0x9b,0x04,0x00,0x0f,0x00,0x09,0xa4,0x04,0x00,0x0f,0x00,0x09,0xad,0x04, +0x00,0x0f,0x00,0x09,0xb6,0x04,0x00,0x0f,0x00,0x09,0xbf,0x04,0x00,0x0f,0x00,0x09, +0xc8,0x04,0x00,0x0f,0x00,0x09,0xd1,0x04,0x00,0x0f,0x00,0x09,0xda,0x04,0x00,0x0f, +0x00,0x09,0xe3,0x04,0x00,0x0f,0x00,0x09,0xec,0x04,0x00,0x0f,0x00,0x09,0xf5,0x04, +0x00,0x0f,0x00,0x09,0xfe,0x04,0x00,0x0f,0x00,0x09,0x07,0x05,0x00,0x0f,0x00,0x09, +0x10,0x05,0x00,0x0f,0x00,0x09,0x19,0x05,0x00,0x0f,0x00,0x09,0x22,0x05,0x00,0x0f, +0x00,0x09,0x2b,0x05,0x00,0x0f,0x00,0x09,0x34,0x05,0x00,0x0f,0x00,0x09,0x3d,0x05, +0x00,0x0f,0x00,0x09,0x46,0x05,0x00,0x0f,0x00,0x09,0x4f,0x05,0x00,0x0f,0x00,0x09, +0x58,0x05,0x00,0x0f,0x00,0x09,0x61,0x05,0x00,0x0f,0x00,0x09,0x6a,0x05,0x00,0x0f, +0x00,0x09,0x73,0x05,0x00,0x0f,0x00,0x09,0x7c,0x05,0x00,0x0f,0x00,0x09,0x85,0x05, +0x00,0x0f,0x00,0x09,0x8e,0x05,0x00,0x0f,0x00,0x09,0x97,0x05,0x00,0x0f,0x00,0x09, +0xa0,0x05,0x00,0x0d,0x00,0x09,0xa9,0x05,0x05,0x0f,0x00,0x09,0xb2,0x05,0x02,0x0e, +0x00,0x09,0xbb,0x05,0x03,0x0d,0x00,0x09,0xc4,0x05,0x03,0x0d,0x00,0x09,0xcd,0x05, +0x03,0x0d,0x00,0x09,0xd6,0x05,0x02,0x0e,0x00,0x09,0xdf,0x05,0x03,0x0e,0x00,0x09, +0xe8,0x05,0x02,0x04,0x00,0x09,0xf1,0x05,0x03,0x0d,0x00,0x09,0xfa,0x05,0x03,0x0a, +0x00,0x09,0x03,0x06,0x06,0x0b,0x00,0x09,0x0c,0x06,0x07,0x0a,0x00,0x09,0x15,0x06, +0x08,0x09,0x00,0x09,0x1e,0x06,0x03,0x0b,0x00,0x09,0x27,0x06,0x02,0x03,0x00,0x09, +0x30,0x06,0x03,0x07,0x00,0x09,0x39,0x06,0x05,0x0c,0x00,0x09,0x42,0x06,0x03,0x0a, +0x00,0x09,0x4b,0x06,0x03,0x0a,0x00,0x09,0x54,0x06,0x02,0x04,0x00,0x09,0x5d,0x06, +0x05,0x0f,0x00,0x09,0x66,0x06,0x03,0x0e,0x00,0x09,0x6f,0x06,0x08,0x0a,0x00,0x09, +0x78,0x06,0x0d,0x0f,0x00,0x09,0x81,0x06,0x03,0x0a,0x00,0x09,0x8a,0x06,0x03,0x0a, +0x00,0x09,0x93,0x06,0x06,0x0b,0x00,0x09,0x9c,0x06,0x03,0x0d,0x00,0x09,0xa5,0x06, +0x03,0x0d,0x00,0x09,0xae,0x06,0x03,0x0d,0x00,0x09,0xb7,0x06,0x05,0x0f,0x00,0x09, +0xc0,0x06,0x00,0x0d,0x00,0x09,0xc9,0x06,0x00,0x0d,0x00,0x09,0xd2,0x06,0x00,0x0d, +0x00,0x09,0xdb,0x06,0x00,0x0d,0x00,0x09,0xe4,0x06,0x00,0x0d,0x00,0x09,0xed,0x06, +0x01,0x0d,0x00,0x09,0xf6,0x06,0x03,0x0d,0x00,0x09,0xff,0x06,0x03,0x0f,0x00,0x09, +0x08,0x07,0x00,0x0d,0x00,0x09,0x11,0x07,0x00,0x0d,0x00,0x09,0x1a,0x07,0x00,0x0d, +0x00,0x09,0x23,0x07,0x00,0x0d,0x00,0x09,0x2c,0x07,0x00,0x0d,0x00,0x09,0x35,0x07, +0x00,0x0d,0x00,0x09,0x3e,0x07,0x00,0x0d,0x00,0x09,0x47,0x07,0x00,0x0d,0x00,0x09, +0x50,0x07,0x03,0x0d,0x00,0x09,0x59,0x07,0x00,0x0d,0x00,0x09,0x62,0x07,0x00,0x0d, +0x00,0x09,0x6b,0x07,0x00,0x0d,0x00,0x09,0x74,0x07,0x00,0x0d,0x00,0x09,0x7d,0x07, +0x00,0x0d,0x00,0x09,0x86,0x07,0x00,0x0d,0x00,0x09,0x8f,0x07,0x06,0x0b,0x00,0x09, +0x98,0x07,0x03,0x0d,0x00,0x09,0xa1,0x07,0x00,0x0d,0x00,0x09,0xaa,0x07,0x00,0x0d, +0x00,0x09,0xb3,0x07,0x00,0x0d,0x00,0x09,0xbc,0x07,0x00,0x0d,0x00,0x09,0xc5,0x07, +0x00,0x0d,0x00,0x09,0xce,0x07,0x03,0x0d,0x00,0x09,0xd7,0x07,0x02,0x0d,0x00,0x09, +0xe0,0x07,0x02,0x0d,0x00,0x09,0xe9,0x07,0x02,0x0d,0x00,0x09,0xf2,0x07,0x02,0x0d, +0x00,0x09,0xfb,0x07,0x02,0x0d,0x00,0x09,0x04,0x08,0x02,0x0d,0x00,0x09,0x0d,0x08, +0x02,0x0d,0x00,0x09,0x16,0x08,0x05,0x0d,0x00,0x09,0x1f,0x08,0x05,0x0f,0x00,0x09, +0x28,0x08,0x02,0x0d,0x00,0x09,0x31,0x08,0x02,0x0d,0x00,0x09,0x3a,0x08,0x02,0x0d, +0x00,0x09,0x43,0x08,0x02,0x0d,0x00,0x09,0x4c,0x08,0x02,0x0d,0x00,0x09,0x55,0x08, +0x02,0x0d,0x00,0x09,0x5e,0x08,0x02,0x0d,0x00,0x09,0x67,0x08,0x02,0x0d,0x00,0x09, +0x70,0x08,0x02,0x0d,0x00,0x09,0x79,0x08,0x02,0x0d,0x00,0x09,0x82,0x08,0x02,0x0d, +0x00,0x09,0x8b,0x08,0x02,0x0d,0x00,0x09,0x94,0x08,0x02,0x0d,0x00,0x09,0x9d,0x08, +0x02,0x0d,0x00,0x09,0xa6,0x08,0x02,0x0d,0x00,0x09,0xaf,0x08,0x05,0x0c,0x00,0x09, +0xb8,0x08,0x05,0x0d,0x00,0x09,0xc1,0x08,0x02,0x0d,0x00,0x09,0xca,0x08,0x02,0x0d, +0x00,0x09,0xd3,0x08,0x02,0x0d,0x00,0x09,0xdc,0x08,0x02,0x0d,0x00,0x09,0xe5,0x08, +0x02,0x0f,0x00,0x09,0xee,0x08,0x03,0x0f,0x00,0x09,0xf7,0x08,0x02,0x0f,0x00,0x09, +0x00,0x09,0x00,0x00,0x00,0x00, +}; + +int sizeofdefont = sizeof defontdata; + +void +_unpackinfo(Fontchar *fc, uchar *p, int n) +{ + int j; + + for(j=0; j<=n; j++){ + fc->x = p[0]|(p[1]<<8); + fc->top = p[2]; + fc->bottom = p[3]; + fc->left = p[4]; + fc->width = p[5]; + fc++; + p += 6; + } +} diff --git a/src/libdraw/draw.c b/src/libdraw/draw.c new file mode 100644 index 00000000..d3f83e88 --- /dev/null +++ b/src/libdraw/draw.c @@ -0,0 +1,69 @@ +#include +#include +#include + +void +_setdrawop(Display *d, Drawop op) +{ + uchar *a; + + if(op != SoverD){ + a = bufimage(d, 1+1); + if(a == 0) + return; + a[0] = 'O'; + a[1] = op; + } +} + +static void +draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1, Drawop op) +{ + uchar *a; + + _setdrawop(dst->display, op); + + a = bufimage(dst->display, 1+4+4+4+4*4+2*4+2*4); + if(a == 0) + return; + if(src == nil) + src = dst->display->black; + if(mask == nil) + mask = dst->display->opaque; + a[0] = 'd'; + BPLONG(a+1, dst->id); + BPLONG(a+5, src->id); + BPLONG(a+9, mask->id); + BPLONG(a+13, r->min.x); + BPLONG(a+17, r->min.y); + BPLONG(a+21, r->max.x); + BPLONG(a+25, r->max.y); + BPLONG(a+29, p0->x); + BPLONG(a+33, p0->y); + BPLONG(a+37, p1->x); + BPLONG(a+41, p1->y); +} + +void +draw(Image *dst, Rectangle r, Image *src, Image *mask, Point p1) +{ + draw1(dst, &r, src, &p1, mask, &p1, SoverD); +} + +void +drawop(Image *dst, Rectangle r, Image *src, Image *mask, Point p1, Drawop op) +{ + draw1(dst, &r, src, &p1, mask, &p1, op); +} + +void +gendraw(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1) +{ + draw1(dst, &r, src, &p0, mask, &p1, SoverD); +} + +void +gendrawop(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1, Drawop op) +{ + draw1(dst, &r, src, &p0, mask, &p1, op); +} diff --git a/src/libdraw/drawrepl.c b/src/libdraw/drawrepl.c new file mode 100644 index 00000000..c72fee26 --- /dev/null +++ b/src/libdraw/drawrepl.c @@ -0,0 +1,23 @@ +#include +#include +#include + +int +drawreplxy(int min, int max, int x) +{ + int sx; + + sx = (x-min)%(max-min); + if(sx < 0) + sx += max-min; + return sx+min; +} + +Point +drawrepl(Rectangle r, Point p) +{ + p.x = drawreplxy(r.min.x, r.max.x, p.x); + p.y = drawreplxy(r.min.y, r.max.y, p.y); + return p; +} + diff --git a/src/libdraw/egetrect.c b/src/libdraw/egetrect.c new file mode 100644 index 00000000..2c5c9848 --- /dev/null +++ b/src/libdraw/egetrect.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#define W Borderwidth + +static Image *tmp[4]; +static Image *red; + +static Cursor sweep={ + {-7, -7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, + 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7, + 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F, + 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,}, + {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2, + 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38, + 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,} +}; + +static +void +brects(Rectangle r, Rectangle rp[4]) +{ + if(Dx(r) < 2*W) + r.max.x = r.min.x+2*W; + if(Dy(r) < 2*W) + r.max.y = r.min.y+2*W; + rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W); + rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y); + rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W); + rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W); +} + +Rectangle +egetrect(int but, Mouse *m) +{ + Rectangle r, rc; + + but = 1<<(but-1); + esetcursor(&sweep); + while(m->buttons) + *m = emouse(); + while(!(m->buttons & but)){ + *m = emouse(); + if(m->buttons & (7^but)) + goto Return; + } + r.min = m->xy; + r.max = m->xy; + do{ + rc = canonrect(r); + edrawgetrect(rc, 1); + *m = emouse(); + edrawgetrect(rc, 0); + r.max = m->xy; + }while(m->buttons == but); + + Return: + esetcursor(0); + if(m->buttons & (7^but)){ + rc.min.x = rc.max.x = 0; + rc.min.y = rc.max.y = 0; + while(m->buttons) + *m = emouse(); + } + return rc; +} + +static +void +freetmp(void) +{ + freeimage(tmp[0]); + freeimage(tmp[1]); + freeimage(tmp[2]); + freeimage(tmp[3]); + freeimage(red); + tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil; +} + +void +edrawgetrect(Rectangle rc, int up) +{ + int i; + Rectangle r, rects[4]; + + if(up && tmp[0]!=nil) + if(Dx(tmp[0]->r)r)r), W); + tmp[0] = allocimage(display, r, screen->chan, 0, -1); + tmp[1] = allocimage(display, r, screen->chan, 0, -1); + r = Rect(0, 0, W, Dy(screen->r)); + tmp[2] = allocimage(display, r, screen->chan, 0, -1); + tmp[3] = allocimage(display, r, screen->chan, 0, -1); + red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed); + if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0) + drawerror(display, "getrect: allocimage failed"); + } + brects(rc, rects); + if(!up){ + for(i=0; i<4; i++) + draw(screen, rects[i], tmp[i], nil, ZP); + return; + } + for(i=0; i<4; i++){ + draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min); + draw(screen, rects[i], red, nil, ZP); + } +} diff --git a/src/libdraw/freesubfont.c b/src/libdraw/freesubfont.c new file mode 100644 index 00000000..6830b9dc --- /dev/null +++ b/src/libdraw/freesubfont.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void +freesubfont(Subfont *f) +{ + if(f == 0) + return; + f->ref--; + if(f->ref > 0) + return; + uninstallsubfont(f); + free(f->info); /* note: f->info must have been malloc'ed! */ + freeimage(f->bits); + free(f); +} diff --git a/src/libdraw/getdefont.c b/src/libdraw/getdefont.c new file mode 100644 index 00000000..9279eec4 --- /dev/null +++ b/src/libdraw/getdefont.c @@ -0,0 +1,60 @@ +#include +#include +#include + +Subfont* +getdefont(Display *d) +{ + char *hdr, *p; + int n; + Fontchar *fc; + Subfont *f; + int ld; + Rectangle r; + Image *i; + + /* + * make sure data is word-aligned. this is true with Plan 9 compilers + * but not in general. the byte order is right because the data is + * declared as char*, not ulong*. + */ + p = (char*)defontdata; + n = (ulong)p & 3; + if(n != 0){ + memmove(p+(4-n), p, sizeofdefont-n); + p += 4-n; + } + ld = atoi(p+0*12); + r.min.x = atoi(p+1*12); + r.min.y = atoi(p+2*12); + r.max.x = atoi(p+3*12); + r.max.y = atoi(p+4*12); + + i = allocimage(d, r, drawld2chan[ld], 0, 0); + if(i == 0) + return 0; + + p += 5*12; + n = loadimage(i, r, (uchar*)p, (defontdata+sizeofdefont)-(uchar*)p); + if(n < 0){ + freeimage(i); + return 0; + } + + hdr = p+n; + n = atoi(hdr); + p = hdr+3*12; + fc = malloc(sizeof(Fontchar)*(n+1)); + if(fc == 0){ + freeimage(i); + return 0; + } + _unpackinfo(fc, (uchar*)p, n); + f = allocsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i); + if(f == 0){ + freeimage(i); + free(fc); + return 0; + } + return f; +} diff --git a/src/libdraw/getrect.c b/src/libdraw/getrect.c new file mode 100644 index 00000000..a050e4c4 --- /dev/null +++ b/src/libdraw/getrect.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +#define W Borderwidth + +static Image *tmp[4]; +static Image *red; + +static Cursor sweep={ + {-7, -7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, + 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7, + 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F, + 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,}, + {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2, + 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38, + 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,} +}; + +static +void +brects(Rectangle r, Rectangle rp[4]) +{ + if(Dx(r) < 2*W) + r.max.x = r.min.x+2*W; + if(Dy(r) < 2*W) + r.max.y = r.min.y+2*W; + rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W); + rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y); + rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W); + rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W); +} + +Rectangle +getrect(int but, Mousectl *mc) +{ + Rectangle r, rc; + + but = 1<<(but-1); + setcursor(mc, &sweep); + while(mc->m.buttons) + readmouse(mc); + while(!(mc->m.buttons & but)){ + readmouse(mc); + if(mc->m.buttons & (7^but)) + goto Return; + } + r.min = mc->m.xy; + r.max = mc->m.xy; + do{ + rc = canonrect(r); + drawgetrect(rc, 1); + readmouse(mc); + drawgetrect(rc, 0); + r.max = mc->m.xy; + }while(mc->m.buttons == but); + + Return: + setcursor(mc, nil); + if(mc->m.buttons & (7^but)){ + rc.min.x = rc.max.x = 0; + rc.min.y = rc.max.y = 0; + while(mc->m.buttons) + readmouse(mc); + } + return rc; +} + +static +void +freetmp(void) +{ + freeimage(tmp[0]); + freeimage(tmp[1]); + freeimage(tmp[2]); + freeimage(tmp[3]); + freeimage(red); + tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil; +} + +static +int +max(int a, int b) +{ + if(a > b) + return a; + return b; +} + +void +drawgetrect(Rectangle rc, int up) +{ + int i; + Rectangle r, rects[4]; + + /* + * BUG: if for some reason we have two of these going on at once + * when we must grow the tmp buffers, we lose data. Also if tmp + * is unallocated and we ask to restore the screen, it would be nice + * to complain, but we silently make a mess. + */ + if(up && tmp[0]!=nil) + if(Dx(tmp[0]->r)r)screenimage->r), Dx(rc)), W); + tmp[0] = allocimage(display, r, screen->chan, 0, -1); + tmp[1] = allocimage(display, r, screen->chan, 0, -1); + r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc))); + tmp[2] = allocimage(display, r, screen->chan, 0, -1); + tmp[3] = allocimage(display, r, screen->chan, 0, -1); + red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed); + if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){ + freetmp(); + drawerror(display, "getrect: allocimage failed"); + } + } + brects(rc, rects); + if(!up){ + for(i=0; i<4; i++) + draw(screen, rects[i], tmp[i], nil, ZP); + return; + } + for(i=0; i<4; i++){ + draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min); + draw(screen, rects[i], red, nil, ZP); + } +} diff --git a/src/libdraw/icossin.c b/src/libdraw/icossin.c new file mode 100644 index 00000000..b66417d4 --- /dev/null +++ b/src/libdraw/icossin.c @@ -0,0 +1,140 @@ +#include +#include +#include + +/* + * Integer sine and cosine for integral degree argument. + * Tables computed by (sin,cos)(PI*d/180). + */ +static short sinus[91] = { + 0, /* 0 */ + 18, /* 1 */ + 36, /* 2 */ + 54, /* 3 */ + 71, /* 4 */ + 89, /* 5 */ + 107, /* 6 */ + 125, /* 7 */ + 143, /* 8 */ + 160, /* 9 */ + 178, /* 10 */ + 195, /* 11 */ + 213, /* 12 */ + 230, /* 13 */ + 248, /* 14 */ + 265, /* 15 */ + 282, /* 16 */ + 299, /* 17 */ + 316, /* 18 */ + 333, /* 19 */ + 350, /* 20 */ + 367, /* 21 */ + 384, /* 22 */ + 400, /* 23 */ + 416, /* 24 */ + 433, /* 25 */ + 449, /* 26 */ + 465, /* 27 */ + 481, /* 28 */ + 496, /* 29 */ + 512, /* 30 */ + 527, /* 31 */ + 543, /* 32 */ + 558, /* 33 */ + 573, /* 34 */ + 587, /* 35 */ + 602, /* 36 */ + 616, /* 37 */ + 630, /* 38 */ + 644, /* 39 */ + 658, /* 40 */ + 672, /* 41 */ + 685, /* 42 */ + 698, /* 43 */ + 711, /* 44 */ + 724, /* 45 */ + 737, /* 46 */ + 749, /* 47 */ + 761, /* 48 */ + 773, /* 49 */ + 784, /* 50 */ + 796, /* 51 */ + 807, /* 52 */ + 818, /* 53 */ + 828, /* 54 */ + 839, /* 55 */ + 849, /* 56 */ + 859, /* 57 */ + 868, /* 58 */ + 878, /* 59 */ + 887, /* 60 */ + 896, /* 61 */ + 904, /* 62 */ + 912, /* 63 */ + 920, /* 64 */ + 928, /* 65 */ + 935, /* 66 */ + 943, /* 67 */ + 949, /* 68 */ + 956, /* 69 */ + 962, /* 70 */ + 968, /* 71 */ + 974, /* 72 */ + 979, /* 73 */ + 984, /* 74 */ + 989, /* 75 */ + 994, /* 76 */ + 998, /* 77 */ + 1002, /* 78 */ + 1005, /* 79 */ + 1008, /* 80 */ + 1011, /* 81 */ + 1014, /* 82 */ + 1016, /* 83 */ + 1018, /* 84 */ + 1020, /* 85 */ + 1022, /* 86 */ + 1023, /* 87 */ + 1023, /* 88 */ + 1024, /* 89 */ + 1024, /* 90 */ +}; + +void +icossin(int deg, int *cosp, int *sinp) +{ + int sinsign, cossign; + short *stp, *ctp; + + deg %= 360; + if(deg < 0) + deg += 360; + sinsign = 1; + cossign = 1; + stp = 0; + ctp = 0; + switch(deg/90){ + case 2: + sinsign = -1; + cossign = -1; + deg -= 180; + /* fall through */ + case 0: + stp = &sinus[deg]; + ctp = &sinus[90-deg]; + break; + case 3: + sinsign = -1; + cossign = -1; + deg -= 180; + /* fall through */ + case 1: + deg = 180-deg; + cossign = -cossign; + stp = &sinus[deg]; + ctp = &sinus[90-deg]; + break; + } + *sinp = sinsign*stp[0]; + *cosp = cossign*ctp[0]; +} diff --git a/src/libdraw/icossin2.c b/src/libdraw/icossin2.c new file mode 100644 index 00000000..aa864e1a --- /dev/null +++ b/src/libdraw/icossin2.c @@ -0,0 +1,261 @@ +#include +#include +#include + +/* + * Sine and Cosine of arctangents, calculated by + * (sin(atan(index/100.0))*1024.+0.5) + * (cos(atan(index/100.0))*1024.+0.5) + * To use, get rational tangent between 0<=tan<=1, scale by 100, + * and look up sin and cos, and use linear interpolation. divide by 1024. + * Maximum error is 0.0020. Without linear interpolation, it's 0.010. + */ +static +short sinus[] = { + 0, /* 0.00 */ + 10, /* 0.01 */ + 20, /* 0.02 */ + 31, /* 0.03 */ + 41, /* 0.04 */ + 51, /* 0.05 */ + 61, /* 0.06 */ + 72, /* 0.07 */ + 82, /* 0.08 */ + 92, /* 0.09 */ + 102, /* 0.10 */ + 112, /* 0.11 */ + 122, /* 0.12 */ + 132, /* 0.13 */ + 142, /* 0.14 */ + 152, /* 0.15 */ + 162, /* 0.16 */ + 172, /* 0.17 */ + 181, /* 0.18 */ + 191, /* 0.19 */ + 201, /* 0.20 */ + 210, /* 0.21 */ + 220, /* 0.22 */ + 230, /* 0.23 */ + 239, /* 0.24 */ + 248, /* 0.25 */ + 258, /* 0.26 */ + 267, /* 0.27 */ + 276, /* 0.28 */ + 285, /* 0.29 */ + 294, /* 0.30 */ + 303, /* 0.31 */ + 312, /* 0.32 */ + 321, /* 0.33 */ + 330, /* 0.34 */ + 338, /* 0.35 */ + 347, /* 0.36 */ + 355, /* 0.37 */ + 364, /* 0.38 */ + 372, /* 0.39 */ + 380, /* 0.40 */ + 388, /* 0.41 */ + 397, /* 0.42 */ + 405, /* 0.43 */ + 412, /* 0.44 */ + 420, /* 0.45 */ + 428, /* 0.46 */ + 436, /* 0.47 */ + 443, /* 0.48 */ + 451, /* 0.49 */ + 458, /* 0.50 */ + 465, /* 0.51 */ + 472, /* 0.52 */ + 480, /* 0.53 */ + 487, /* 0.54 */ + 493, /* 0.55 */ + 500, /* 0.56 */ + 507, /* 0.57 */ + 514, /* 0.58 */ + 520, /* 0.59 */ + 527, /* 0.60 */ + 533, /* 0.61 */ + 540, /* 0.62 */ + 546, /* 0.63 */ + 552, /* 0.64 */ + 558, /* 0.65 */ + 564, /* 0.66 */ + 570, /* 0.67 */ + 576, /* 0.68 */ + 582, /* 0.69 */ + 587, /* 0.70 */ + 593, /* 0.71 */ + 598, /* 0.72 */ + 604, /* 0.73 */ + 609, /* 0.74 */ + 614, /* 0.75 */ + 620, /* 0.76 */ + 625, /* 0.77 */ + 630, /* 0.78 */ + 635, /* 0.79 */ + 640, /* 0.80 */ + 645, /* 0.81 */ + 649, /* 0.82 */ + 654, /* 0.83 */ + 659, /* 0.84 */ + 663, /* 0.85 */ + 668, /* 0.86 */ + 672, /* 0.87 */ + 676, /* 0.88 */ + 681, /* 0.89 */ + 685, /* 0.90 */ + 689, /* 0.91 */ + 693, /* 0.92 */ + 697, /* 0.93 */ + 701, /* 0.94 */ + 705, /* 0.95 */ + 709, /* 0.96 */ + 713, /* 0.97 */ + 717, /* 0.98 */ + 720, /* 0.99 */ + 724, /* 1.00 */ + 728, /* 1.01 */ +}; + +static +short cosinus[] = { + 1024, /* 0.00 */ + 1024, /* 0.01 */ + 1024, /* 0.02 */ + 1024, /* 0.03 */ + 1023, /* 0.04 */ + 1023, /* 0.05 */ + 1022, /* 0.06 */ + 1022, /* 0.07 */ + 1021, /* 0.08 */ + 1020, /* 0.09 */ + 1019, /* 0.10 */ + 1018, /* 0.11 */ + 1017, /* 0.12 */ + 1015, /* 0.13 */ + 1014, /* 0.14 */ + 1013, /* 0.15 */ + 1011, /* 0.16 */ + 1010, /* 0.17 */ + 1008, /* 0.18 */ + 1006, /* 0.19 */ + 1004, /* 0.20 */ + 1002, /* 0.21 */ + 1000, /* 0.22 */ + 998, /* 0.23 */ + 996, /* 0.24 */ + 993, /* 0.25 */ + 991, /* 0.26 */ + 989, /* 0.27 */ + 986, /* 0.28 */ + 983, /* 0.29 */ + 981, /* 0.30 */ + 978, /* 0.31 */ + 975, /* 0.32 */ + 972, /* 0.33 */ + 969, /* 0.34 */ + 967, /* 0.35 */ + 963, /* 0.36 */ + 960, /* 0.37 */ + 957, /* 0.38 */ + 954, /* 0.39 */ + 951, /* 0.40 */ + 947, /* 0.41 */ + 944, /* 0.42 */ + 941, /* 0.43 */ + 937, /* 0.44 */ + 934, /* 0.45 */ + 930, /* 0.46 */ + 927, /* 0.47 */ + 923, /* 0.48 */ + 920, /* 0.49 */ + 916, /* 0.50 */ + 912, /* 0.51 */ + 909, /* 0.52 */ + 905, /* 0.53 */ + 901, /* 0.54 */ + 897, /* 0.55 */ + 893, /* 0.56 */ + 890, /* 0.57 */ + 886, /* 0.58 */ + 882, /* 0.59 */ + 878, /* 0.60 */ + 874, /* 0.61 */ + 870, /* 0.62 */ + 866, /* 0.63 */ + 862, /* 0.64 */ + 859, /* 0.65 */ + 855, /* 0.66 */ + 851, /* 0.67 */ + 847, /* 0.68 */ + 843, /* 0.69 */ + 839, /* 0.70 */ + 835, /* 0.71 */ + 831, /* 0.72 */ + 827, /* 0.73 */ + 823, /* 0.74 */ + 819, /* 0.75 */ + 815, /* 0.76 */ + 811, /* 0.77 */ + 807, /* 0.78 */ + 804, /* 0.79 */ + 800, /* 0.80 */ + 796, /* 0.81 */ + 792, /* 0.82 */ + 788, /* 0.83 */ + 784, /* 0.84 */ + 780, /* 0.85 */ + 776, /* 0.86 */ + 773, /* 0.87 */ + 769, /* 0.88 */ + 765, /* 0.89 */ + 761, /* 0.90 */ + 757, /* 0.91 */ + 754, /* 0.92 */ + 750, /* 0.93 */ + 746, /* 0.94 */ + 742, /* 0.95 */ + 739, /* 0.96 */ + 735, /* 0.97 */ + 731, /* 0.98 */ + 728, /* 0.99 */ + 724, /* 1.00 */ + 720, /* 1.01 */ +}; + +void +icossin2(int x, int y, int *cosp, int *sinp) +{ + int sinsign, cossign, tan, tan10, rem; + short *stp, *ctp; + + if(x == 0){ + if(y >= 0) + *sinp = ICOSSCALE, *cosp = 0; + else + *sinp = -ICOSSCALE, *cosp = 0; + return; + } + sinsign = cossign = 1; + if(x < 0){ + cossign = -1; + x = -x; + } + if(y < 0){ + sinsign = -1; + y = -y; + } + if(y > x){ + tan = 1000*x/y; + tan10 = tan/10; + stp = &cosinus[tan10]; + ctp = &sinus[tan10]; + }else{ + tan = 1000*y/x; + tan10 = tan/10; + stp = &sinus[tan10]; + ctp = &cosinus[tan10]; + } + rem = tan-(tan10*10); + *sinp = sinsign*(stp[0]+(stp[1]-stp[0])*rem/10); + *cosp = cossign*(ctp[0]+(ctp[1]-ctp[0])*rem/10); +} diff --git a/src/libdraw/line.c b/src/libdraw/line.c new file mode 100644 index 00000000..a06b5927 --- /dev/null +++ b/src/libdraw/line.c @@ -0,0 +1,35 @@ +#include +#include +#include + +void +line(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp) +{ + lineop(dst, p0, p1, end0, end1, radius, src, sp, SoverD); +} + +void +lineop(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp, Drawop op) +{ + uchar *a; + + _setdrawop(dst->display, op); + + a = bufimage(dst->display, 1+4+2*4+2*4+4+4+4+4+2*4); + if(a == 0){ + fprint(2, "image line: %r\n"); + return; + } + a[0] = 'L'; + BPLONG(a+1, dst->id); + BPLONG(a+5, p0.x); + BPLONG(a+9, p0.y); + BPLONG(a+13, p1.x); + BPLONG(a+17, p1.y); + BPLONG(a+21, end0); + BPLONG(a+25, end1); + BPLONG(a+29, radius); + BPLONG(a+33, src->id); + BPLONG(a+37, sp.x); + BPLONG(a+41, sp.y); +} diff --git a/src/libdraw/loadimage.c b/src/libdraw/loadimage.c new file mode 100644 index 00000000..d8d8c40b --- /dev/null +++ b/src/libdraw/loadimage.c @@ -0,0 +1,54 @@ +#include +#include +#include + +int +loadimage(Image *i, Rectangle r, uchar *data, int ndata) +{ + long dy; + int n, bpl; + uchar *a; + int chunk; + + chunk = i->display->bufsize - 64; + + if(!rectinrect(r, i->r)){ + werrstr("loadimage: bad rectangle"); + return -1; + } + bpl = bytesperline(r, i->depth); + n = bpl*Dy(r); + if(n > ndata){ + werrstr("loadimage: insufficient data"); + return -1; + } + ndata = 0; + while(r.max.y > r.min.y){ + dy = r.max.y - r.min.y; + if(dy*bpl > chunk) + dy = chunk/bpl; + if(dy <= 0){ + werrstr("loadimage: image too wide for buffer"); + return -1; + } + n = dy*bpl; + a = bufimage(i->display, 21+n); + if(a == nil){ + werrstr("bufimage failed"); + return -1; + } + a[0] = 'y'; + BPLONG(a+1, i->id); + BPLONG(a+5, r.min.x); + BPLONG(a+9, r.min.y); + BPLONG(a+13, r.max.x); + BPLONG(a+17, r.min.y+dy); + memmove(a+21, data, n); + ndata += n; + data += n; + r.min.y += dy; + } + if(flushimage(i->display, 0) < 0) + return -1; + return ndata; +} diff --git a/src/libdraw/mkfont.c b/src/libdraw/mkfont.c new file mode 100644 index 00000000..df6b0ec2 --- /dev/null +++ b/src/libdraw/mkfont.c @@ -0,0 +1,55 @@ +#include +#include +#include + +/* + * Cobble fake font using existing subfont + */ +Font* +mkfont(Subfont *subfont, Rune min) +{ + Font *font; + Cachefont *c; + + font = malloc(sizeof(Font)); + if(font == 0) + return 0; + memset(font, 0, sizeof(Font)); + font->display = subfont->bits->display; + font->name = strdup(""); + font->ncache = NFCACHE+NFLOOK; + font->nsubf = NFSUBF; + font->cache = malloc(font->ncache * sizeof(font->cache[0])); + font->subf = malloc(font->nsubf * sizeof(font->subf[0])); + if(font->name==0 || font->cache==0 || font->subf==0){ + Err: + free(font->name); + free(font->cache); + free(font->subf); + free(font->sub); + free(font); + return 0; + } + memset(font->cache, 0, font->ncache*sizeof(font->cache[0])); + memset(font->subf, 0, font->nsubf*sizeof(font->subf[0])); + font->height = subfont->height; + font->ascent = subfont->ascent; + font->age = 1; + font->sub = malloc(sizeof(Cachefont*)); + if(font->sub == 0) + goto Err; + c = malloc(sizeof(Cachefont)); + if(c == 0) + goto Err; + font->nsub = 1; + font->sub[0] = c; + c->min = min; + c->max = min+subfont->n-1; + c->offset = 0; + c->name = 0; /* noticed by freeup() and agefont() */ + c->subfontname = 0; + font->subf[0].age = 0; + font->subf[0].cf = c; + font->subf[0].f = subfont; + return font; +} diff --git a/src/libdraw/newwindow.c b/src/libdraw/newwindow.c new file mode 100644 index 00000000..88784adf --- /dev/null +++ b/src/libdraw/newwindow.c @@ -0,0 +1,27 @@ +#include +#include +#include + +/* Connect us to new window, if possible */ +int +newwindow(char *str) +{ + int fd; + char *wsys; + char buf[256]; + + wsys = getenv("wsys"); + if(wsys == nil) + return -1; + fd = open(wsys, ORDWR); + free(wsys); + if(fd < 0) + return -1; + rfork(RFNAMEG); + if(str) + snprint(buf, sizeof buf, "new %s", str); + else + strcpy(buf, "new"); + return mount(fd, -1, "/dev", MBEFORE, buf); +} + diff --git a/src/libdraw/poly.c b/src/libdraw/poly.c new file mode 100644 index 00000000..96effaec --- /dev/null +++ b/src/libdraw/poly.c @@ -0,0 +1,87 @@ +#include +#include +#include + +static +uchar* +addcoord(uchar *p, int oldx, int newx) +{ + int dx; + + dx = newx-oldx; + /* does dx fit in 7 signed bits? */ + if((unsigned)(dx - -0x40) <= 0x7F) + *p++ = dx&0x7F; + else{ + *p++ = 0x80 | (newx&0x7F); + *p++ = newx>>7; + *p++ = newx>>15; + } + return p; +} + +static +void +dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, Image *src, Point *sp, Drawop op) +{ + uchar *a, *t, *u; + int i, ox, oy; + + if(np == 0) + return; + t = malloc(np*2*3); + if(t == nil) + return; + u = t; + ox = oy = 0; + for(i=0; idisplay, op); + + a = bufimage(dst->display, 1+4+2+4+4+4+4+2*4+(u-t)); + if(a == 0){ + free(t); + fprint(2, "image poly: %r\n"); + return; + } + a[0] = cmd; + BPLONG(a+1, dst->id); + BPSHORT(a+5, np-1); + BPLONG(a+7, end0); + BPLONG(a+11, end1); + BPLONG(a+15, radius); + BPLONG(a+19, src->id); + BPLONG(a+23, sp->x); + BPLONG(a+27, sp->y); + memmove(a+31, t, u-t); + free(t); +} + +void +poly(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp) +{ + dopoly('p', dst, p, np, end0, end1, radius, src, &sp, SoverD); +} + +void +polyop(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp, Drawop op) +{ + dopoly('p', dst, p, np, end0, end1, radius, src, &sp, op); +} + +void +fillpoly(Image *dst, Point *p, int np, int wind, Image *src, Point sp) +{ + dopoly('P', dst, p, np, wind, 0, 0, src, &sp, SoverD); +} + +void +fillpolyop(Image *dst, Point *p, int np, int wind, Image *src, Point sp, Drawop op) +{ + dopoly('P', dst, p, np, wind, 0, 0, src, &sp, op); +} diff --git a/src/libdraw/rectclip.c b/src/libdraw/rectclip.c new file mode 100644 index 00000000..2228628b --- /dev/null +++ b/src/libdraw/rectclip.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int +rectclip(Rectangle *rp, Rectangle b) /* first by reference, second by value */ +{ + Rectangle *bp = &b; + /* + * Expand rectXrect() in line for speed + */ + if((rp->min.xmax.x && bp->min.xmax.x && + rp->min.ymax.y && bp->min.ymax.y)==0) + return 0; + /* They must overlap */ + if(rp->min.x < bp->min.x) + rp->min.x = bp->min.x; + if(rp->min.y < bp->min.y) + rp->min.y = bp->min.y; + if(rp->max.x > bp->max.x) + rp->max.x = bp->max.x; + if(rp->max.y > bp->max.y) + rp->max.y = bp->max.y; + return 1; +} diff --git a/src/libdraw/replclipr.c b/src/libdraw/replclipr.c new file mode 100644 index 00000000..ffd24b47 --- /dev/null +++ b/src/libdraw/replclipr.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void +replclipr(Image *i, int repl, Rectangle clipr) +{ + uchar *b; + + b = bufimage(i->display, 22); + b[0] = 'c'; + BPLONG(b+1, i->id); + repl = repl!=0; + b[5] = repl; + BPLONG(b+6, clipr.min.x); + BPLONG(b+10, clipr.min.y); + BPLONG(b+14, clipr.max.x); + BPLONG(b+18, clipr.max.y); + i->repl = repl; + i->clipr = clipr; +} diff --git a/src/libdraw/rgb.c b/src/libdraw/rgb.c new file mode 100644 index 00000000..e8f7f51b --- /dev/null +++ b/src/libdraw/rgb.c @@ -0,0 +1,99 @@ +#include +#include +#include + +/* + * This original version, although fast and a true inverse of + * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c)) + * returned the original color, does a terrible job for RGB + * triples that do not appear in the color map, so it has been + * replaced by the much slower version below, that loops + * over the color map looking for the nearest point in RGB + * space. There is no visual psychology reason for that + * criterion, but it's easy to implement and the results are + * far more pleasing. + * +int +rgb2cmap(int cr, int cg, int cb) +{ + int r, g, b, v, cv; + + if(cr < 0) + cr = 0; + else if(cr > 255) + cr = 255; + if(cg < 0) + cg = 0; + else if(cg > 255) + cg = 255; + if(cb < 0) + cb = 0; + else if(cb > 255) + cb = 255; + r = cr>>6; + g = cg>>6; + b = cb>>6; + cv = cr; + if(cg > cv) + cv = cg; + if(cb > cv) + cv = cb; + v = (cv>>4)&3; + return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15)); +} +*/ + +int +rgb2cmap(int cr, int cg, int cb) +{ + int i, r, g, b, sq; + u32int rgb; + int best, bestsq; + + best = 0; + bestsq = 0x7FFFFFFF; + for(i=0; i<256; i++){ + rgb = cmap2rgb(i); + r = (rgb>>16) & 0xFF; + g = (rgb>>8) & 0xFF; + b = (rgb>>0) & 0xFF; + sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb); + if(sq < bestsq){ + bestsq = sq; + best = i; + } + } + return best; +} + +int +cmap2rgb(int c) +{ + int j, num, den, r, g, b, v, rgb; + + r = c>>6; + v = (c>>4)&3; + j = (c-v+r)&15; + g = j>>2; + b = j&3; + den=r; + if(g>den) + den=g; + if(b>den) + den=b; + if(den==0) { + v *= 17; + rgb = (v<<16)|(v<<8)|v; + } + else{ + num=17*(4*den+v); + rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den); + } + return rgb; +} + +int +cmap2rgba(int c) +{ + return (cmap2rgb(c)<<8)|0xFF; +} diff --git a/src/libdraw/stringbg.c b/src/libdraw/stringbg.c new file mode 100644 index 00000000..0628a840 --- /dev/null +++ b/src/libdraw/stringbg.c @@ -0,0 +1,51 @@ +#include +#include +#include + +Point +stringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp) +{ + return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, SoverD); +} + +Point +stringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp, Drawop op) +{ + return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, op); +} + +Point +stringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp) +{ + return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, SoverD); +} + +Point +stringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp, Drawop op) +{ + return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, op); +} + +Point +runestringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp) +{ + return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, SoverD); +} + +Point +runestringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp, Drawop op) +{ + return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, op); +} + +Point +runestringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp) +{ + return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, SoverD); +} + +Point +runestringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp, Drawop op) +{ + return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, op); +} diff --git a/src/libdraw/stringsubfont.c b/src/libdraw/stringsubfont.c new file mode 100644 index 00000000..cc834732 --- /dev/null +++ b/src/libdraw/stringsubfont.c @@ -0,0 +1,65 @@ +#include +#include +#include + +Point +stringsubfont(Image *b, Point p, Image *color, Subfont *f, char *cs) +{ + int w, width; + uchar *s; + Rune c; + Fontchar *i; + + s = (uchar*)cs; + for(; c=*s; p.x+=width){ + width = 0; + if(c < Runeself) + s++; + else{ + w = chartorune(&c, (char*)s); + if(w == 0){ + s++; + continue; + } + s += w; + } + if(c >= f->n) + continue; + i = f->info+c; + width = i->width; + draw(b, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom), + color, f->bits, Pt(i->x, i->top)); + } + return p; +} + +Point +strsubfontwidth(Subfont *f, char *cs) +{ + Rune c; + Point p; + uchar *s; + Fontchar *i; + int w, width; + + p = Pt(0, f->height); + s = (uchar*)cs; + for(; c=*s; p.x+=width){ + width = 0; + if(c < Runeself) + s++; + else{ + w = chartorune(&c, (char*)s); + if(w == 0){ + s++; + continue; + } + s += w; + } + if(c >= f->n) + continue; + i = f->info+c; + width = i->width; + } + return p; +} diff --git a/src/libdraw/test.c b/src/libdraw/test.c new file mode 100644 index 00000000..d4a5de77 --- /dev/null +++ b/src/libdraw/test.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +void +eresized(int new) +{ + if(new && getwindow(display, Refnone) < 0){ + fprint(2, "colors: can't reattach to window: %r\n"); + exits("resized"); + } + draw(screen, screen->r, display->white, nil, ZP); + flushimage(display, 1); +} + +char *buttons[] = +{ + "exit", + 0 +}; + +Menu menu = +{ + buttons +}; + +void +main(int argc, char *argv[]) +{ + Mouse m; + + initdraw(0,0,0); + eresized(0); + einit(Emouse); + for(;;){ + m = emouse(); + if(m.buttons == 4) + switch(emenuhit(3, &m, &menu)){ + case 0: + exits(0); + } + } +} diff --git a/src/libdraw/window.c b/src/libdraw/window.c new file mode 100644 index 00000000..b82c25e9 --- /dev/null +++ b/src/libdraw/window.c @@ -0,0 +1,214 @@ +#include +#include +#include + +typedef struct Memimage Memimage; + +static int screenid; + +Screen* +allocscreen(Image *image, Image *fill, int public) +{ + uchar *a; + Screen *s; + int id, try; + Display *d; + + d = image->display; + if(d != fill->display){ + werrstr("allocscreen: image and fill on different displays"); + return 0; + } + s = malloc(sizeof(Screen)); + if(s == 0) + return 0; + SET(id); + for(try=0; try<25; try++){ + /* loop until find a free id */ + a = bufimage(d, 1+4+4+4+1); + if(a == 0){ + free(s); + return 0; + } + id = ++screenid; + a[0] = 'A'; + BPLONG(a+1, id); + BPLONG(a+5, image->id); + BPLONG(a+9, fill->id); + a[13] = public; + if(flushimage(d, 0) != -1) + break; + } + s->display = d; + s->id = id; + s->image = image; + assert(s->image && s->image->chan != 0); + + s->fill = fill; + return s; +} + +Screen* +publicscreen(Display *d, int id, u32int chan) +{ + uchar *a; + Screen *s; + + s = malloc(sizeof(Screen)); + if(s == 0) + return 0; + a = bufimage(d, 1+4+4); + if(a == 0){ + Error: + free(s); + return 0; + } + a[0] = 'S'; + BPLONG(a+1, id); + BPLONG(a+5, chan); + if(flushimage(d, 0) < 0) + goto Error; + + s->display = d; + s->id = id; + s->image = 0; + s->fill = 0; + return s; +} + +int +freescreen(Screen *s) +{ + uchar *a; + Display *d; + + if(s == 0) + return 0; + d = s->display; + a = bufimage(d, 1+4); + if(a == 0) + return -1; + a[0] = 'F'; + BPLONG(a+1, s->id); + /* + * flush(1) because screen is likely holding last reference to + * window, and want it to disappear visually. + */ + if(flushimage(d, 1) < 0) + return -1; + free(s); + return 1; +} + +Image* +allocwindow(Screen *s, Rectangle r, int ref, u32int val) +{ + return _allocwindow(nil, s, r, ref, val); +} + +Image* +_allocwindow(Image *i, Screen *s, Rectangle r, int ref, u32int val) +{ + Display *d; + + d = s->display; + i = _allocimage(i, d, r, d->screenimage->chan, 0, val, s->id, ref); + if(i == 0) + return 0; + i->screen = s; + i->next = s->display->windows; + s->display->windows = i; + return i; +} + +static +void +topbottom(Image **w, int n, int top) +{ + int i; + uchar *b; + Display *d; + + if(n < 0){ + Ridiculous: + fprint(2, "top/bottom: ridiculous number of windows\n"); + return; + } + if(n == 0) + return; + if(n > (w[0]->display->bufsize-100)/4) + goto Ridiculous; + /* + * this used to check that all images were on the same screen. + * we don't know the screen associated with images we acquired + * by name. instead, check that all images are on the same display. + * the display will check that they are all on the same screen. + */ + d = w[0]->display; + for(i=1; idisplay != d){ + fprint(2, "top/bottom: windows not on same screen\n"); + return; + } + + if(n==0) + return; + b = bufimage(d, 1+1+2+4*n); + b[0] = 't'; + b[1] = top; + BPSHORT(b+2, n); + for(i=0; iid); +} + +void +bottomwindow(Image *w) +{ + if(w->screen == 0) + return; + topbottom(&w, 1, 0); +} + +void +topwindow(Image *w) +{ + if(w->screen == 0) + return; + topbottom(&w, 1, 1); +} + +void +bottomnwindows(Image **w, int n) +{ + topbottom(w, n, 0); +} + +void +topnwindows(Image **w, int n) +{ + topbottom(w, n, 1); +} + +int +originwindow(Image *w, Point log, Point scr) +{ + uchar *b; + Point delta; + + flushimage(w->display, 0); + b = bufimage(w->display, 1+4+2*4+2*4); + if(b == nil) + return 0; + b[0] = 'o'; + BPLONG(b+1, w->id); + BPLONG(b+5, log.x); + BPLONG(b+9, log.y); + BPLONG(b+13, scr.x); + BPLONG(b+17, scr.y); + if(flushimage(w->display, 1) < 0) + return -1; + delta = subpt(log, w->r.min); + w->r = rectaddpt(w->r, delta); + w->clipr = rectaddpt(w->clipr, delta); + return 1; +} diff --git a/src/libdraw/writeimage.c b/src/libdraw/writeimage.c new file mode 100644 index 00000000..b4dcff06 --- /dev/null +++ b/src/libdraw/writeimage.c @@ -0,0 +1,185 @@ +#include +#include +#include + +#define HSHIFT 3 /* HSHIFT==5 runs slightly faster, but hash table is 64x bigger */ +#define NHASH (1<<(HSHIFT*NMATCH)) +#define HMASK (NHASH-1) +#define hupdate(h, c) ((((h)<display->bufsize - 32; /* a little room for header */ + r = i->r; + bpl = bytesperline(r, i->depth); + n = Dy(r)*bpl; + data = malloc(n); + ncblock = _compblocksize(r, i->depth); + outbuf = malloc(ncblock); + hash = malloc(NHASH*sizeof(Hlist)); + chain = malloc(NMEM*sizeof(Hlist)); + if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){ + ErrOut: + free(data); + free(outbuf); + free(hash); + free(chain); + return -1; + } + for(miny = r.min.y; miny != r.max.y; miny += dy){ + dy = r.max.y-miny; + if(dy*bpl > chunk) + dy = chunk/bpl; + if(dolock) + lockdisplay(i->display); + nb = unloadimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), + data+(miny-r.min.y)*bpl, dy*bpl); + if(dolock) + unlockdisplay(i->display); + if(nb != dy*bpl) + goto ErrOut; + } + sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ", + chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y); + if(write(fd, hdr, 11+5*12) != 11+5*12) + goto ErrOut; + edata = data+n; + eout = outbuf+ncblock; + line = data; + r.max.y = r.min.y; + while(line != edata){ + memset(hash, 0, NHASH*sizeof(Hlist)); + memset(chain, 0, NMEM*sizeof(Hlist)); + cp = chain; + h = 0; + outp = outbuf; + for(n = 0; n != NMATCH; n++) + h = hupdate(h, line[n]); + loutp = outbuf; + while(line != edata){ + ndump = 0; + eline = line+bpl; + for(p = line; p != eline; ){ + if(eline-p < NRUN) + es = eline; + else + es = p+NRUN; + q = 0; + runlen = 0; + for(hp = hash[h].next; hp; hp = hp->next){ + s = p + runlen; + if(s >= es) + continue; + t = hp->s + runlen; + for(; s >= p; s--) + if(*s != *t--) + goto matchloop; + t += runlen+2; + s += runlen+2; + for(; s < es; s++) + if(*s != *t++) + break; + n = s-p; + if(n > runlen){ + runlen = n; + q = hp->s; + if(n == NRUN) + break; + } + matchloop: ; + } + if(runlen < NMATCH){ + if(ndump == NDUMP){ + if(eout-outp < ndump+1) + goto Bfull; + *outp++ = ndump-1+128; + memmove(outp, dumpbuf, ndump); + outp += ndump; + ndump = 0; + } + dumpbuf[ndump++] = *p; + runlen = 1; + } + else{ + if(ndump != 0){ + if(eout-outp < ndump+1) + goto Bfull; + *outp++ = ndump-1+128; + memmove(outp, dumpbuf, ndump); + outp += ndump; + ndump = 0; + } + offs = p-q-1; + if(eout-outp < 2) + goto Bfull; + *outp++ = ((runlen-NMATCH)<<2) + (offs>>8); + *outp++ = offs&255; + } + for(q = p+runlen; p != q; p++){ + if(cp->prev) + cp->prev->next = 0; + cp->next = hash[h].next; + cp->prev = &hash[h]; + if(cp->next) + cp->next->prev = cp; + cp->prev->next = cp; + cp->s = p; + if(++cp == &chain[NMEM]) + cp = chain; + if(edata-p > NMATCH) + h = hupdate(h, p[NMATCH]); + } + } + if(ndump != 0){ + if(eout-outp < ndump+1) + goto Bfull; + *outp++ = ndump-1+128; + memmove(outp, dumpbuf, ndump); + outp += ndump; + } + line = eline; + loutp = outp; + r.max.y++; + } + Bfull: + if(loutp == outbuf) + goto ErrOut; + n = loutp-outbuf; + sprint(hdr, "%11d %11ld ", r.max.y, n); + write(fd, hdr, 2*12); + write(fd, outbuf, n); + r.min.y = r.max.y; + } + free(data); + free(outbuf); + free(hash); + free(chain); + return 0; +} diff --git a/src/libdraw/writesubfont.c b/src/libdraw/writesubfont.c new file mode 100644 index 00000000..1ea985f0 --- /dev/null +++ b/src/libdraw/writesubfont.c @@ -0,0 +1,45 @@ +#include +#include +#include + +static +void +packinfo(Fontchar *fc, uchar *p, int n) +{ + int j; + + for(j=0; j<=n; j++){ + p[0] = fc->x; + p[1] = fc->x>>8; + p[2] = fc->top; + p[3] = fc->bottom; + p[4] = fc->left; + p[5] = fc->width; + fc++; + p += 6; + } +} + +int +writesubfont(int fd, Subfont *f) +{ + char hdr[3*12+1]; + uchar *data; + int nb; + + sprint(hdr, "%11d %11d %11d ", f->n, f->height, f->ascent); + if(write(fd, hdr, 3*12) != 3*12){ + Err: + werrstr("writesubfont: bad write: %r"); + return -1; + } + nb = 6*(f->n+1); + data = malloc(nb); + if(data == nil) + return -1; + packinfo(f->info, data, f->n); + if(write(fd, data, nb) != nb) + goto Err; + free(data); + return 0; +}