1 #include <lib9.h> 2 #include <kernel.h> 3 #include "draw.h" 4 #include "tk.h" 5 #include "canvs.h" 6 7 #define O(t, e) ((long)(&((t*)0)->e)) 8 9 /* Rectangle Options (+ means implemented) 10 +fill 11 +outline 12 +stipple 13 +tags 14 +width 15 */ 16 17 typedef struct TkCrect TkCrect; 18 struct TkCrect 19 { 20 int width; 21 Image* stipple; 22 }; 23 24 static 25 TkOption rectopts[] = 26 { 27 "width", OPTnnfrac, O(TkCrect, width), nil, 28 "stipple", OPTbmap, O(TkCrect, stipple), nil, 29 nil 30 }; 31 32 static 33 TkOption itemopts[] = 34 { 35 "tags", OPTctag, O(TkCitem, tags), nil, 36 "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill), 37 "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd), 38 nil 39 }; 40 41 void 42 tkcvsrectsize(TkCitem *i) 43 { 44 TkCrect *r; 45 int w; 46 47 r = TKobj(TkCrect, i); 48 w = TKF2I(r->width)*2; 49 50 i->p.bb = bbnil; 51 tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb); 52 i->p.bb = insetrect(i->p.bb, -w); 53 } 54 55 static void 56 tkmkstipple(Image *stipple) 57 { 58 int locked; 59 if (stipple != nil && !stipple->repl) { 60 locked = lockdisplay(stipple->display); 61 replclipr(stipple, 1, huger); 62 if (locked) 63 unlockdisplay(stipple->display); 64 } 65 } 66 67 char* 68 tkcvsrectcreat(Tk* tk, char *arg, char **val) 69 { 70 char *e; 71 TkCrect *r; 72 TkCitem *i; 73 TkCanvas *c; 74 TkOptab tko[3]; 75 76 c = TKobj(TkCanvas, tk); 77 78 i = tkcnewitem(tk, TkCVrect, sizeof(TkCitem)+sizeof(TkCrect)); 79 if(i == nil) 80 return TkNomem; 81 82 r = TKobj(TkCrect, i); 83 r->width = TKI2F(1); 84 85 e = tkparsepts(tk->env->top, &i->p, &arg, 0); 86 if(e != nil) { 87 tkcvsfreeitem(i); 88 return e; 89 } 90 if(i->p.npoint != 2) { 91 tkcvsfreeitem(i); 92 return TkFewpt; 93 } 94 95 tko[0].ptr = r; 96 tko[0].optab = rectopts; 97 tko[1].ptr = i; 98 tko[1].optab = itemopts; 99 tko[2].ptr = nil; 100 e = tkparse(tk->env->top, arg, tko, nil); 101 if(e != nil) { 102 tkcvsfreeitem(i); 103 return e; 104 } 105 tkmkstipple(r->stipple); 106 e = tkcaddtag(tk, i, 1); 107 if(e != nil) { 108 tkcvsfreeitem(i); 109 return e; 110 } 111 112 tkcvsrectsize(i); 113 e = tkvalue(val, "%d", i->id); 114 if(e != nil) { 115 tkcvsfreeitem(i); 116 return e; 117 } 118 tkcvsappend(c, i); 119 120 tkbbmax(&c->update, &i->p.bb); 121 tkcvssetdirty(tk); 122 return nil; 123 } 124 125 char* 126 tkcvsrectcget(TkCitem *i, char *arg, char **val) 127 { 128 TkOptab tko[3]; 129 TkCrect *r = TKobj(TkCrect, i); 130 131 tko[0].ptr = r; 132 tko[0].optab = rectopts; 133 tko[1].ptr = i; 134 tko[1].optab = itemopts; 135 tko[2].ptr = nil; 136 137 return tkgencget(tko, arg, val, i->env->top); 138 } 139 140 char* 141 tkcvsrectconf(Tk *tk, TkCitem *i, char *arg) 142 { 143 char *e; 144 TkOptab tko[3]; 145 TkCrect *r = TKobj(TkCrect, i); 146 147 tko[0].ptr = r; 148 tko[0].optab = rectopts; 149 tko[1].ptr = i; 150 tko[1].optab = itemopts; 151 tko[2].ptr = nil; 152 153 e = tkparse(tk->env->top, arg, tko, nil); 154 tkcvsrectsize(i); 155 tkmkstipple(r->stipple); 156 return e; 157 } 158 159 void 160 tkcvsrectfree(TkCitem *i) 161 { 162 TkCrect *r; 163 164 r = TKobj(TkCrect, i); 165 if(r->stipple) 166 freeimage(r->stipple); 167 } 168 169 void 170 tkcvsrectdraw(Image *img, TkCitem *i, TkEnv *pe) 171 { 172 int lw, rw; 173 TkEnv *e; 174 TkCrect *r; 175 Rectangle d, rr; 176 Point tr, bl; 177 Image *pen; 178 179 USED(pe); 180 181 d.min = i->p.drawpt[0]; 182 d.max = i->p.drawpt[1]; 183 184 e = i->env; 185 r = TKobj(TkCrect, i); 186 187 pen = nil; 188 if((e->set & (1<<TkCfill))) 189 pen = tkgc(e, TkCfill); 190 191 if(pen != nil) 192 draw(img, d, pen, r->stipple, d.min); 193 194 tr.x = d.max.x; 195 tr.y = d.min.y; 196 bl.x = d.min.x; 197 bl.y = d.max.y; 198 199 rw = (TKF2I(r->width) + 1)/2; 200 if(rw <= 0) 201 return; 202 lw = (TKF2I(r->width))/2; 203 204 pen = tkgc(e, TkCforegnd); 205 if(pen != nil) { 206 /* horizontal lines first */ 207 rr.min.x = d.min.x - lw; 208 rr.max.x = d.max.x + rw; 209 rr.min.y = d.min.y - lw; 210 rr.max.y = d.min.y + rw; 211 draw(img, rr, pen, nil, rr.min); 212 rr.min.y += Dy(d); 213 rr.max.y += Dy(d); 214 draw(img, rr, pen, nil, rr.min); 215 /* now the vertical */ 216 /* horizontal lines first */ 217 rr.min.x = d.min.x - lw; 218 rr.max.x = d.min.x + rw; 219 rr.min.y = d.min.y + rw; 220 rr.max.y = d.max.y - lw; 221 draw(img, rr, pen, nil, rr.min); 222 rr.min.x += Dx(d); 223 rr.max.x += Dx(d); 224 draw(img, rr, pen, nil, rr.min); 225 } 226 } 227 228 char* 229 tkcvsrectcoord(TkCitem *i, char *arg, int x, int y) 230 { 231 char *e; 232 TkCpoints p; 233 234 if(arg == nil) { 235 tkxlatepts(i->p.parampt, i->p.npoint, x, y); 236 tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y)); 237 i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y))); 238 } 239 else { 240 e = tkparsepts(i->env->top, &p, &arg, 0); 241 if(e != nil) 242 return e; 243 if(p.npoint != 2) { 244 tkfreepoint(&p); 245 return TkFewpt; 246 } 247 tkfreepoint(&i->p); 248 i->p = p; 249 tkcvsrectsize(i); 250 } 251 return nil; 252 } 253