summaryrefslogtreecommitdiff
path: root/libtk/cline.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libtk/cline.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libtk/cline.c')
-rw-r--r--libtk/cline.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/libtk/cline.c b/libtk/cline.c
new file mode 100644
index 00000000..8d50871b
--- /dev/null
+++ b/libtk/cline.c
@@ -0,0 +1,268 @@
+#include "lib9.h"
+#include "draw.h"
+#include "tk.h"
+#include "canvs.h"
+
+#define O(t, e) ((long)(&((t*)0)->e))
+
+/* Line Options (+ means implemented)
+ +arrow
+ +arrowshape
+ +capstyle
+ +fill
+ joinstyle
+ +smooth
+ +splinesteps
+ +stipple
+ +tags
+ +width
+*/
+
+static
+TkStab tklines[] =
+{
+ "none", 0,
+ "first", TkCarrowf,
+ "last", TkCarrowl,
+ "both", TkCarrowf|TkCarrowl,
+ nil
+};
+
+static
+TkStab tkcapstyle[] =
+{
+ "butt", Endsquare,
+ "projecting", Endsquare,
+ "round", Enddisc,
+ nil
+};
+
+static
+TkOption lineopts[] =
+{
+ "arrow", OPTstab, O(TkCline, arrow), tklines,
+ "arrowshape", OPTfrac, O(TkCline, shape[0]), IAUX(3),
+ "width", OPTnnfrac, O(TkCline, width), nil,
+ "stipple", OPTbmap, O(TkCline, stipple), nil,
+ "smooth", OPTstab, O(TkCline, smooth), tkbool,
+ "splinesteps", OPTdist, O(TkCline, steps), nil,
+ "capstyle", OPTstab, O(TkCline, capstyle), tkcapstyle,
+ nil
+};
+
+static
+TkOption itemopts[] =
+{
+ "tags", OPTctag, O(TkCitem, tags), nil,
+ "fill", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd),
+ nil
+};
+
+void
+tkcvslinesize(TkCitem *i)
+{
+ TkCline *l;
+ int j, w, as, shape[3], arrow;
+
+ l = TKobj(TkCline, i);
+ w = TKF2I(l->width);
+
+ i->p.bb = bbnil;
+ tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
+
+ l->arrowf = l->capstyle;
+ l->arrowl = l->capstyle;
+ if(l->arrow != 0) {
+ as = w/3;
+ if(as < 1)
+ as = 1;
+ for(j = 0; j < 3; j++) {
+ shape[j] = l->shape[j];
+ if(shape[j] == 0)
+ shape[j] = as * cvslshape[j];
+ }
+ arrow = ARROW(TKF2I(shape[0]), TKF2I(shape[1]), TKF2I(shape[2]));
+ if(l->arrow & TkCarrowf)
+ l->arrowf = arrow;
+ if(l->arrow & TkCarrowl)
+ l->arrowl = arrow;
+ w += shape[2];
+ }
+
+ i->p.bb = insetrect(i->p.bb, -w);
+}
+
+char*
+tkcvslinecreat(Tk* tk, char *arg, char **val)
+{
+ char *e;
+ TkCline *l;
+ TkCitem *i;
+ TkCanvas *c;
+ TkOptab tko[3];
+
+ c = TKobj(TkCanvas, tk);
+
+ i = tkcnewitem(tk, TkCVline, sizeof(TkCitem)+sizeof(TkCline));
+ if(i == nil)
+ return TkNomem;
+
+ l = TKobj(TkCline, i);
+ l->width = TKI2F(1);
+
+ e = tkparsepts(tk->env->top, &i->p, &arg, 0);
+ if(e != nil) {
+ tkcvsfreeitem(i);
+ return e;
+ }
+
+ tko[0].ptr = l;
+ tko[0].optab = lineopts;
+ 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;
+ }
+ tkmkpen(&l->pen, i->env, l->stipple);
+
+ e = tkcaddtag(tk, i, 1);
+ if(e != nil) {
+ tkcvsfreeitem(i);
+ return e;
+ }
+
+ tkcvslinesize(i);
+ e = tkvalue(val, "%d", i->id);
+ if(e != nil) {
+ tkcvsfreeitem(i);
+ return e;
+ }
+ tkcvsappend(c, i);
+
+ tkbbmax(&c->update, &i->p.bb);
+ tkcvssetdirty(tk);
+ return nil;
+}
+
+char*
+tkcvslinecget(TkCitem *i, char *arg, char **val)
+{
+ TkOptab tko[3];
+ TkCline *l = TKobj(TkCline, i);
+
+ tko[0].ptr = l;
+ tko[0].optab = lineopts;
+ tko[1].ptr = i;
+ tko[1].optab = itemopts;
+ tko[2].ptr = nil;
+
+ return tkgencget(tko, arg, val, i->env->top);
+}
+
+char*
+tkcvslineconf(Tk *tk, TkCitem *i, char *arg)
+{
+ char *e;
+ TkOptab tko[3];
+ TkCline *l = TKobj(TkCline, i);
+
+ tko[0].ptr = l;
+ tko[0].optab = lineopts;
+ tko[1].ptr = i;
+ tko[1].optab = itemopts;
+ tko[2].ptr = nil;
+
+ e = tkparse(tk->env->top, arg, tko, nil);
+
+ tkmkpen(&l->pen, i->env, l->stipple);
+ tkcvslinesize(i);
+
+ return e;
+}
+
+void
+tkcvslinefree(TkCitem *i)
+{
+ TkCline *l;
+
+ l = TKobj(TkCline, i);
+ if(l->stipple)
+ freeimage(l->stipple);
+ if(l->pen)
+ freeimage(l->pen);
+}
+
+void
+tkcvslinedraw(Image *img, TkCitem *i, TkEnv *pe)
+{
+ int w;
+ Point *p;
+ TkCline *l;
+ Image *pen;
+
+ USED(pe);
+
+ l = TKobj(TkCline, i);
+
+ pen = l->pen;
+ if(pen == nil)
+ pen = tkgc(i->env, TkCforegnd);
+
+ w = TKF2I(l->width)/2;
+ if(w < 0)
+ return;
+
+ p = i->p.drawpt;
+ if(l->smooth == BoolT && i->p.npoint >= 3)
+ bezspline(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
+ else
+ poly(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
+}
+
+char*
+tkcvslinecoord(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;
+ tkcvslinesize(i);
+ }
+ return nil;
+}
+
+int
+tkcvslinehit(TkCitem *i, Point p)
+{
+ TkCline *l;
+ int w, np, r;
+ Point *pp;
+
+ l = TKobj(TkCline, i);
+ w =TKF2I(l->width) + 2; /* 2 for slop */
+
+ if (l->smooth == BoolT) {
+ np = getbezsplinepts(i->p.drawpt, i->p.npoint, &pp);
+ r = tklinehit(pp, np, w, p);
+ free(pp);
+ } else
+ r = tklinehit(i->p.drawpt, i->p.npoint, w, p);
+ return r;
+}