diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libtk/carcs.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libtk/carcs.c')
| -rw-r--r-- | libtk/carcs.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/libtk/carcs.c b/libtk/carcs.c new file mode 100644 index 00000000..ded91fd6 --- /dev/null +++ b/libtk/carcs.c @@ -0,0 +1,280 @@ +#include "lib9.h" +#include "draw.h" +#include "tk.h" +#include "canvs.h" + +#define O(t, e) ((long)(&((t*)0)->e)) +typedef void (*Drawfn)(Image*, Point, int, int, Image*, int); + +/* Arc Options (+ means implemented) + +extent + +fill + +outline + outlinestipple + +start + +stipple + +style (+pieslice chord +arc) + +tags + +width +*/ + +typedef struct TkCarc TkCarc; +struct TkCarc +{ + int width; + int start; + int extent; + int style; + Image* stipple; + Image* pen; +}; + +enum Style +{ + Pieslice, + Chord, + Arc +}; + +static +TkStab tkstyle[] = +{ + "pieslice", Pieslice, + "arc", Arc, + "chord", Arc, /* Can't do chords */ + nil +}; + +static +TkOption arcopts[] = +{ + "start", OPTfrac, O(TkCarc, start), nil, + "extent", OPTfrac, O(TkCarc, extent), nil, + "style", OPTstab, O(TkCarc, style), tkstyle, + "width", OPTnnfrac, O(TkCarc, width), nil, + "stipple", OPTbmap, O(TkCarc, stipple), nil, + nil +}; + +static +TkOption itemopts[] = +{ + "tags", OPTctag, O(TkCitem, tags), nil, + "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill), + "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd), + nil +}; + +void +tkcvsarcsize(TkCitem *i) +{ + int w; + TkCarc *a; + + a = TKobj(TkCarc, i); + w = TKF2I(a->width)*2; + + i->p.bb = bbnil; + tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb); + i->p.bb = insetrect(i->p.bb, -w); +} + +char* +tkcvsarccreat(Tk* tk, char *arg, char **val) +{ + char *e; + TkCarc *a; + TkCitem *i; + TkCanvas *c; + TkOptab tko[3]; + + c = TKobj(TkCanvas, tk); + + i = tkcnewitem(tk, TkCVarc, sizeof(TkCitem)+sizeof(TkCarc)); + if(i == nil) + return TkNomem; + + a = TKobj(TkCarc, i); + a->width = TKI2F(1); + + e = tkparsepts(tk->env->top, &i->p, &arg, 0); + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + if(i->p.npoint != 2) { + tkcvsfreeitem(i); + return TkFewpt; + } + + tko[0].ptr = a; + tko[0].optab = arcopts; + tko[1].ptr = i; + tko[1].optab = itemopts; + tko[2].ptr = nil; + e = tkparse(tk->env->top, arg, tko, nil); + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + + e = tkcaddtag(tk, i, 1); + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + + tkcvsarcsize(i); + tkmkpen(&a->pen, i->env, a->stipple); + + tkcvsappend(c, i); + + tkbbmax(&c->update, &i->p.bb); + tkcvssetdirty(tk); + return tkvalue(val, "%d", i->id); +} + +char* +tkcvsarccget(TkCitem *i, char *arg, char **val) +{ + TkOptab tko[3]; + TkCarc *a = TKobj(TkCarc, i); + + tko[0].ptr = a; + tko[0].optab = arcopts; + tko[1].ptr = i; + tko[1].optab = itemopts; + tko[2].ptr = nil; + + return tkgencget(tko, arg, val, i->env->top); +} + +char* +tkcvsarcconf(Tk *tk, TkCitem *i, char *arg) +{ + char *e; + TkOptab tko[3]; + TkCarc *a = TKobj(TkCarc, i); + + tko[0].ptr = a; + tko[0].optab = arcopts; + tko[1].ptr = i; + tko[1].optab = itemopts; + tko[2].ptr = nil; + + e = tkparse(tk->env->top, arg, tko, nil); + tkcvsarcsize(i); + tkmkpen(&a->pen, i->env, a->stipple); + + return e; +} + + +void +tkcvsarcfree(TkCitem *i) +{ + TkCarc *a; + + a = TKobj(TkCarc, i); + if(a->stipple) + freeimage(a->stipple); + if(a->pen) + freeimage(a->pen); +} + +void +tkcvsarcdraw(Image *img, TkCitem *i, TkEnv *pe) +{ + TkEnv *e; + TkCarc *a; + Rectangle d; + int w, dx, dy; + int s, ext, s0, s1, e0, e1, l; + Image *pen, *col, *tmp; + Point p0, p1, c; + extern void drawarc(Point,int,int,int,int,int,Image *,Image *,Image *); + + USED(pe); + + d.min = i->p.drawpt[0]; + d.max = i->p.drawpt[1]; + + e = i->env; + a = TKobj(TkCarc, i); + + pen = a->pen; + if(pen == nil && (e->set & (1<<TkCfill))) + pen = tkgc(e, TkCfill); + + w = TKF2I(a->width)/2; + if(w < 0) + return; + + d = canonrect(d); + dx = Dx(d)/2; + dy = Dy(d)/2; + c.x = (d.min.x+d.max.x)/2; + c.y = (d.min.y+d.max.y)/2; + s = TKF2I(a->start); + ext = TKF2I(a->extent); +/* + if(ext == 0) + ext = 90; +*/ + + if(a->style != Arc && pen != nil) + fillarc(img, c, dx, dy, pen, Pt(0,0), s, ext); + col = tkgc(e, TkCforegnd); + arc(img, c, dx, dy, w, col, Pt(0,0), s, ext); + if(a->style == Pieslice){ + /* + * It is difficult to compute the intersection of the lines + * and the ellipse using integers, so let the draw library + * do it for us: use a full ellipse as the source of color + * for drawing the lines. + */ + tmp = allocimage(img->display, d, img->chan, 0, DNofill); + if(tmp == nil) + return; + /* copy dest to tmp so lines don't spill beyond edge of ellipse */ + drawop(tmp, d, img, nil, d.min, S); + fillellipse(tmp, c, dx, dy, col, Pt(0,0)); + icossin(s, &s1, &s0); + icossin(s+ext, &e1, &e0); + if(dx > dy) + l = 2*dx+1; + else + l = 2*dy+1; + p0 = Pt(c.x+l*s1/ICOSSCALE, c.y-l*s0/ICOSSCALE); + p1 = Pt(c.x+l*e1/ICOSSCALE, c.y-l*e0/ICOSSCALE); + line(img, c, p0, Endsquare, Endsquare, w, tmp, c); + line(img, c, p1, Endsquare, Endsquare, w, tmp, c); + freeimage(tmp); + } +} + +char* +tkcvsarccoord(TkCitem *i, char *arg, int x, int y) +{ + char *e; + TkCpoints p; + + if(arg == nil) { + tkxlatepts(i->p.parampt, i->p.npoint, x, y); + tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y)); + i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y))); + } + else { + e = tkparsepts(i->env->top, &p, &arg, 0); + if(e != nil) + return e; + if(p.npoint != 2) { + tkfreepoint(&p); + return TkFewpt; + } + tkfreepoint(&i->p); + i->p = p; + tkcvsarcsize(i); + } + return nil; +} |
