summaryrefslogtreecommitdiff
path: root/libtk/crect.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtk/crect.c')
-rw-r--r--libtk/crect.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/libtk/crect.c b/libtk/crect.c
new file mode 100644
index 00000000..909eafab
--- /dev/null
+++ b/libtk/crect.c
@@ -0,0 +1,252 @@
+#include <lib9.h>
+#include <kernel.h>
+#include "draw.h"
+#include "tk.h"
+#include "canvs.h"
+
+#define O(t, e) ((long)(&((t*)0)->e))
+
+/* Rectangle Options (+ means implemented)
+ +fill
+ +outline
+ +stipple
+ +tags
+ +width
+*/
+
+typedef struct TkCrect TkCrect;
+struct TkCrect
+{
+ int width;
+ Image* stipple;
+};
+
+static
+TkOption rectopts[] =
+{
+ "width", OPTnnfrac, O(TkCrect, width), nil,
+ "stipple", OPTbmap, O(TkCrect, 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
+tkcvsrectsize(TkCitem *i)
+{
+ TkCrect *r;
+ int w;
+
+ r = TKobj(TkCrect, i);
+ w = TKF2I(r->width)*2;
+
+ i->p.bb = bbnil;
+ tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
+ i->p.bb = insetrect(i->p.bb, -w);
+}
+
+static void
+tkmkstipple(Image *stipple)
+{
+ int locked;
+ if (stipple != nil && !stipple->repl) {
+ locked = lockdisplay(stipple->display);
+ replclipr(stipple, 1, huger);
+ if (locked)
+ unlockdisplay(stipple->display);
+ }
+}
+
+char*
+tkcvsrectcreat(Tk* tk, char *arg, char **val)
+{
+ char *e;
+ TkCrect *r;
+ TkCitem *i;
+ TkCanvas *c;
+ TkOptab tko[3];
+
+ c = TKobj(TkCanvas, tk);
+
+ i = tkcnewitem(tk, TkCVrect, sizeof(TkCitem)+sizeof(TkCrect));
+ if(i == nil)
+ return TkNomem;
+
+ r = TKobj(TkCrect, i);
+ r->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 = r;
+ tko[0].optab = rectopts;
+ 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;
+ }
+ tkmkstipple(r->stipple);
+ e = tkcaddtag(tk, i, 1);
+ if(e != nil) {
+ tkcvsfreeitem(i);
+ return e;
+ }
+
+ tkcvsrectsize(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*
+tkcvsrectcget(TkCitem *i, char *arg, char **val)
+{
+ TkOptab tko[3];
+ TkCrect *r = TKobj(TkCrect, i);
+
+ tko[0].ptr = r;
+ tko[0].optab = rectopts;
+ tko[1].ptr = i;
+ tko[1].optab = itemopts;
+ tko[2].ptr = nil;
+
+ return tkgencget(tko, arg, val, i->env->top);
+}
+
+char*
+tkcvsrectconf(Tk *tk, TkCitem *i, char *arg)
+{
+ char *e;
+ TkOptab tko[3];
+ TkCrect *r = TKobj(TkCrect, i);
+
+ tko[0].ptr = r;
+ tko[0].optab = rectopts;
+ tko[1].ptr = i;
+ tko[1].optab = itemopts;
+ tko[2].ptr = nil;
+
+ e = tkparse(tk->env->top, arg, tko, nil);
+ tkcvsrectsize(i);
+ tkmkstipple(r->stipple);
+ return e;
+}
+
+void
+tkcvsrectfree(TkCitem *i)
+{
+ TkCrect *r;
+
+ r = TKobj(TkCrect, i);
+ if(r->stipple)
+ freeimage(r->stipple);
+}
+
+void
+tkcvsrectdraw(Image *img, TkCitem *i, TkEnv *pe)
+{
+ int lw, rw;
+ TkEnv *e;
+ TkCrect *r;
+ Rectangle d, rr;
+ Point tr, bl;
+ Image *pen;
+
+ USED(pe);
+
+ d.min = i->p.drawpt[0];
+ d.max = i->p.drawpt[1];
+
+ e = i->env;
+ r = TKobj(TkCrect, i);
+
+ pen = nil;
+ if((e->set & (1<<TkCfill)))
+ pen = tkgc(e, TkCfill);
+
+ if(pen != nil)
+ draw(img, d, pen, r->stipple, d.min);
+
+ tr.x = d.max.x;
+ tr.y = d.min.y;
+ bl.x = d.min.x;
+ bl.y = d.max.y;
+
+ rw = (TKF2I(r->width) + 1)/2;
+ if(rw <= 0)
+ return;
+ lw = (TKF2I(r->width))/2;
+
+ pen = tkgc(e, TkCforegnd);
+ if(pen != nil) {
+ /* horizontal lines first */
+ rr.min.x = d.min.x - lw;
+ rr.max.x = d.max.x + rw;
+ rr.min.y = d.min.y - lw;
+ rr.max.y = d.min.y + rw;
+ draw(img, rr, pen, nil, rr.min);
+ rr.min.y += Dy(d);
+ rr.max.y += Dy(d);
+ draw(img, rr, pen, nil, rr.min);
+ /* now the vertical */
+ /* horizontal lines first */
+ rr.min.x = d.min.x - lw;
+ rr.max.x = d.min.x + rw;
+ rr.min.y = d.min.y + rw;
+ rr.max.y = d.max.y - lw;
+ draw(img, rr, pen, nil, rr.min);
+ rr.min.x += Dx(d);
+ rr.max.x += Dx(d);
+ draw(img, rr, pen, nil, rr.min);
+ }
+}
+
+char*
+tkcvsrectcoord(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;
+ tkcvsrectsize(i);
+ }
+ return nil;
+}