void swcursorinit(void) { static int init; if(!init){ init = 1; addclock0link(swcursorclock, 10); swenabled = 1; } if(swback){ freememimage(swback); freememimage(swmask); freememimage(swmask1); freememimage(swimg); freememimage(swimg1); } swback = allocmemimage(Rect(0,0,32,32), gscreen->chan); swmask = allocmemimage(Rect(0,0,16,16), GREY8); swmask1 = allocmemimage(Rect(0,0,16,16), GREY1); swimg = allocmemimage(Rect(0,0,16,16), GREY8); swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ print("software cursor: allocmemimage fails\n"); return; } memfillcolor(swmask, DOpaque); memfillcolor(swmask1, DOpaque); memfillcolor(swimg, DBlack); memfillcolor(swimg1, DBlack); }
void swcursorinit(void) { static int init, warned; VGAscr *scr; didswcursorinit = 1; if(!init){ init = 1; addclock0link(swcursorclock, 10); } scr = &vgascreen[0]; if(scr==nil || scr->gscreen==nil) return; if(scr->dev == nil || scr->dev->linear == nil){ if(!warned){ print("cannot use software cursor on non-linear vga screen\n"); warned = 1; } return; } if(swback){ freememimage(swback); freememimage(swmask); freememimage(swmask1); freememimage(swimg); freememimage(swimg1); } swback = allocmemimage(Rect(0,0,32,32), gscreen->chan); swmask = allocmemimage(Rect(0,0,16,16), GREY8); swmask1 = allocmemimage(Rect(0,0,16,16), GREY1); swimg = allocmemimage(Rect(0,0,16,16), GREY8); swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ print("software cursor: allocmemimage fails"); return; } memfillcolor(swmask, DOpaque); memfillcolor(swmask1, DOpaque); memfillcolor(swimg, DBlack); memfillcolor(swimg1, DBlack); }
Memimage* allocrepl(ulong color) { Memimage *m; m = allocmemimage(Rect(0,0,1,1), RGB24); memfillcolor(m, color); m->flags |= Frepl; m->clipr = Rect(-1000000, -1000000, 1000000, 1000000); return m; }
static void screenwin(void) { Point p; char *greet; Memimage *grey; drawqlock(); back = memwhite; conscol = memblack; memfillcolor(gscreen, 0x444488FF); h = memdefont->height; window.min = addpt(gscreen->r.min, Pt(20,20)); window.max.x = window.min.x + Dx(gscreen->r)*3/4-40; window.max.y = window.min.y + Dy(gscreen->r)*3/4-100; memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); window = insetrect(window, 4); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); /* a lot of work to get a grey color */ grey = allocmemimage(Rect(0,0,1,1), CMAP8); grey->flags |= Frepl; grey->clipr = gscreen->r; memfillcolor(grey, 0xAAAAAAFF); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); freememimage(grey); window = insetrect(window, 5); greet = " Plan 9 Console "; p = addpt(window.min, Pt(10, 0)); memimagestring(gscreen, p, conscol, ZP, memdefont, greet); window.min.y += h+6; curpos = window.min; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; flushmemscreen(gscreen->r); drawqunlock(); }
void vgaimageinit(ulong chan) { if(back == nil){ back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ if(back == nil) panic("back alloc"); /* RSC BUG */ back->flags |= Frepl; back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); memfillcolor(back, DBlack); } if(conscol == nil){ conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ if(conscol == nil) panic("conscol alloc"); /* RSC BUG */ conscol->flags |= Frepl; conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); memfillcolor(conscol, DWhite); } }
void screeninit(int x, int y, char *chanstr) { Point p, q; char *greet; char buf[128]; Memimage *grey; Rectangle r; int chan; cursorver = 0; memimageinit(); chan = strtochan(chanstr); if(chan == 0) error("bad screen channel string"); r = Rect(0, 0, x, y); gscreen = allocmemimage(r, chan); if(gscreen == nil){ snprint(buf, sizeof buf, "can't allocate screen image: %r"); error(buf); } offscreen = Pt(x + 100, y + 100); cursorr = Rect(0, 0, CURSORDIM, CURSORDIM); cursorset = allocmemimage(cursorr, GREY8); cursorclear = allocmemimage(cursorr, GREY1); if(cursorset == nil || cursorclear == nil){ freememimage(gscreen); freememimage(cursorset); freememimage(cursorclear); gscreen = nil; cursorset = nil; cursorclear = nil; snprint(buf, sizeof buf, "can't allocate cursor images: %r"); error(buf); } drawlock(); /* * set up goo for screenputs */ memdefont = getmemdefont(); back = memwhite; conscol = memblack; /* a lot of work to get a grey color */ curscol = allocmemimage(Rect(0,0,1,1), RGBA32); curscol->flags |= Frepl; curscol->clipr = gscreen->r; memfillcolor(curscol, 0xff0000ff); memfillcolor(gscreen, 0x444488FF); w = memdefont->info[' '].width; h = memdefont->height; window.min = addpt(gscreen->r.min, Pt(20,20)); window.max.x = window.min.x + Dx(gscreen->r)*3/4-40; window.max.y = window.min.y + Dy(gscreen->r)*3/4-100; memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); window = insetrect(window, 4); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); /* a lot of work to get a grey color */ grey = allocmemimage(Rect(0,0,1,1), CMAP8); grey->flags |= Frepl; grey->clipr = gscreen->r; memfillcolor(grey, 0xAAAAAAFF); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); freememimage(grey); window = insetrect(window, 5); greet = " Plan 9 Console "; p = addpt(window.min, Pt(10, 0)); q = memsubfontwidth(memdefont, greet); memimagestring(gscreen, p, conscol, ZP, memdefont, greet); window.min.y += h+6; curpos = window.min; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; flushmemscreen(gscreen->r); drawunlock(); setcursor(&arrow); }
Memimage* statgraph(Graph *g) { int i, nbin, x, lo, hi, min, max, first; Memimage *m; Rectangle r; Statbin *b, bin[2000]; /* 32 kB, but whack is worse */ needstack(8192); /* double check that bin didn't kill us */ if(g->wid <= MinWidth) g->wid = DefaultWidth; if(g->ht <= MinHeight) g->ht = DefaultHeight; if(g->wid > nelem(bin)) g->wid = nelem(bin); if(g->fill < 0) g->fill = ((uint)(uintptr)g->arg>>8)%nelem(lofill); if(g->fill > nelem(lofill)) g->fill %= nelem(lofill); nbin = g->wid - (Left+Right); binstats(g->fn, g->arg, g->t0, g->t1, bin, nbin); /* * compute bounds */ min = g->min; max = g->max; if(min < 0 || max <= min){ min = max = 0; first = 1; for(i=0; i<nbin; i++){ b = &bin[i]; if(b->nsamp == 0) continue; if(first || b->min < min) min = b->min; if(first || b->max > max) max = b->max; first = 0; } } qlock(&memdrawlock); ginit(); if(smallfont==nil || black==nil || blue==nil || red==nil || hifill[0]==nil || lofill[0]==nil){ werrstr("graphics initialization failed: %r"); qunlock(&memdrawlock); return nil; } /* fresh image */ m = allocmemimage(Rect(0,0,g->wid,g->ht), ABGR32); if(m == nil){ qunlock(&memdrawlock); return nil; } r = Rect(Left, Top, g->wid-Right, g->ht-Bottom); memfillcolor(m, DTransparent); /* x axis */ memimagedraw(m, Rect(r.min.x, r.max.y, r.max.x, r.max.y+1), black, ZP, memopaque, ZP, S); /* y labels */ drawlabel(m, r.min, max); if(min != 0) drawlabel(m, Pt(r.min.x, r.max.y-smallfont->height), min); /* actual data */ for(i=0; i<nbin; i++){ b = &bin[i]; if(b->nsamp == 0) continue; lo = scalept(b->min, min, max, r.max.y, r.min.y); hi = scalept(b->max, min, max, r.max.y, r.min.y); x = r.min.x+i; hi-=2; memimagedraw(m, Rect(x, hi, x+1,lo), hifill[g->fill%nelem(hifill)], ZP, memopaque, ZP, S); memimagedraw(m, Rect(x, lo, x+1, r.max.y), lofill[g->fill%nelem(lofill)], ZP, memopaque, ZP, S); } if(bin[nbin-1].nsamp) drawlabel(m, Pt(r.max.x, r.min.y+(Dy(r)-smallfont->height)/2), bin[nbin-1].avg); qunlock(&memdrawlock); return m; }
Memimage* memlalloc(Memscreen *s, Rectangle screenr, Refreshfn refreshfn, void *refreshptr, ulong val) { Memlayer *l; Memimage *n; static Memimage *paint; if(paint == nil){ paint = allocmemimage(Rect(0,0,1,1), RGBA32); if(paint == nil) return nil; paint->flags |= Frepl; paint->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); } n = allocmemimaged(screenr, s->image->chan, s->image->data); if(n == nil) return nil; l = malloc(sizeof(Memlayer)); if(l == nil){ free(n); return nil; } l->screen = s; if(refreshfn) l->save = nil; else{ l->save = allocmemimage(screenr, s->image->chan); if(l->save == nil){ free(l); free(n); return nil; } /* allocmemimage doesn't initialize memory; this paints save area */ if(val != DNofill) memfillcolor(l->save, val); } l->refreshfn = refreshfn; l->refreshptr = nil; /* don't set it until we're done */ l->screenr = screenr; l->delta = Pt(0,0); n->data->ref++; n->zero = s->image->zero; n->width = s->image->width; n->layer = l; /* start with new window behind all existing ones */ l->front = s->rearmost; l->rear = nil; if(s->rearmost) s->rearmost->layer->rear = n; s->rearmost = n; if(s->frontmost == nil) s->frontmost = n; l->clear = 0; /* now pull new window to front */ _memltofrontfill(n, val != DNofill); l->refreshptr = refreshptr; /* * paint with requested color; previously exposed areas are already right * if this window has backing store, but just painting the whole thing is simplest. */ if(val != DNofill){ memsetchan(paint, n->chan); memfillcolor(paint, val); memdraw(n, n->r, paint, n->r.min, nil, n->r.min, S); } return n; }
/* * make a "wedge" mask covering the desired angle and contained in * a surrounding square; draw a full ellipse; intersect that with the * wedge to make a mask through which to copy src to dst. */ void memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op) { int i, w, beta, tmp, c1, c2, m, m1; Rectangle rect; Point p, bnd[8]; Memimage *wedge, *figure, *mask; if(a < 0) a = -a; if(b < 0) b = -b; w = t; if(w < 0) w = 0; alpha = -alpha; /* compensate for upside-down coords */ phi = -phi; beta = alpha + phi; if(phi < 0){ tmp = alpha; alpha = beta; beta = tmp; phi = -phi; } if(phi >= 360){ memellipse(dst, c, a, b, t, src, sp, op); return; } while(alpha < 0) alpha += 360; while(beta < 0) beta += 360; c1 = alpha/90 & 3; /* number of nearest corner */ c2 = beta/90 & 3; /* * icossin returns point at radius ICOSSCALE. * multiplying by m1 moves it outside the ellipse */ rect = Rect(-a-w, -b-w, a+w+1, b+w+1); m = rect.max.x; /* inradius of bounding square */ if(m < rect.max.y) m = rect.max.y; m1 = (m+ICOSSCALE-1) >> 10; m = m1 << 10; /* assure m1*cossin is inside */ i = 0; bnd[i++] = Pt(0,0); icossin(alpha, &p.x, &p.y); bnd[i++] = mulpt(p, m1); for(;;) { bnd[i++] = mulpt(corners[c1], m); if(c1==c2 && phi<180) break; c1 = (c1+1) & 3; phi -= 90; } icossin(beta, &p.x, &p.y); bnd[i++] = mulpt(p, m1); figure = nil; mask = nil; wedge = allocmemimage(rect, GREY1); if(wedge == nil) goto Return; memfillcolor(wedge, DTransparent); memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S); figure = allocmemimage(rect, GREY1); if(figure == nil) goto Return; memfillcolor(figure, DTransparent); memellipse(figure, p00, a, b, t, memopaque, p00, S); mask = allocmemimage(rect, GREY1); if(mask == nil) goto Return; memfillcolor(mask, DTransparent); memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S); c = subpt(c, dst->r.min); memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op); Return: freememimage(wedge); freememimage(figure); freememimage(mask); }
Memsubfont* mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias) { CFStringRef s; CGColorSpaceRef color; CGContextRef ctxt; CTFontRef font; CTFontDescriptorRef desc; CGRect bbox; Memimage *m, *mc, *m1; int x, y, y0; int i, height, ascent; Fontchar *fc, *fc0; Memsubfont *sf; CGFloat whitef[] = { 1.0, 1.0 }; CGColorRef white; s = c2mac(name); desc = CTFontDescriptorCreateWithNameAndSize(s, size); CFRelease(s); if(desc == nil) return nil; font = CTFontCreateWithFontDescriptor(desc, 0, nil); CFRelease(desc); if(font == nil) return nil; bbox = CTFontGetBoundingBox(font); x = (int)(bbox.size.width*2 + 0.99999999); fontheight(f, size, &height, &ascent); y = height; y0 = height - ascent; m = allocmemimage(Rect(0, 0, x*(hi+1-lo)+1, y+1), GREY8); if(m == nil) return nil; mc = allocmemimage(Rect(0, 0, x+1, y+1), GREY8); if(mc == nil){ freememimage(m); return nil; } memfillcolor(m, DBlack); memfillcolor(mc, DBlack); fc = malloc((hi+2 - lo) * sizeof fc[0]); sf = malloc(sizeof *sf); if(fc == nil || sf == nil) { freememimage(m); freememimage(mc); free(fc); free(sf); return nil; } fc0 = fc; color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8, mc->width*sizeof(u32int), color, kCGImageAlphaNone); white = CGColorCreate(color, whitef); CGColorSpaceRelease(color); if(ctxt == nil) { freememimage(m); freememimage(mc); free(fc); free(sf); return nil; } CGContextSetAllowsAntialiasing(ctxt, antialias); CGContextSetTextPosition(ctxt, 0, 0); // XXX #if OSX_VERSION >= 101400 CGContextSetAllowsFontSmoothing(ctxt, false); #endif x = 0; for(i=lo; i<=hi; i++, fc++) { char buf[20]; CFStringRef str; CFDictionaryRef attrs; CFAttributedStringRef attrString; CTLineRef line; CGRect r; CGPoint p1; CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; CFTypeRef values[] = { font, white }; sprint(buf, "%C", (Rune)mapUnicode(name, i)); str = c2mac(buf); // See https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW2 attrs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); attrString = CFAttributedStringCreate(kCFAllocatorDefault, str, attrs); CFRelease(str); CFRelease(attrs); line = CTLineCreateWithAttributedString(attrString); CGContextSetTextPosition(ctxt, 0, y0); r = CTLineGetImageBounds(line, ctxt); memfillcolor(mc, DBlack); CTLineDraw(line, ctxt); CFRelease(line); fc->x = x; fc->top = 0; fc->bottom = Dy(m->r); // fprint(2, "printed %#x: %g %g\n", mapUnicode(i), p1.x, p1.y); p1 = CGContextGetTextPosition(ctxt); if(p1.x <= 0 || mapUnicode(name, i) == 0xfffd) { fc->width = 0; fc->left = 0; if(i == 0) { drawpjw(m, fc, x, (int)(bbox.size.width + 0.99999999), y, y - y0); x += fc->width; } continue; } memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S); fc->width = p1.x; fc->left = 0; x += p1.x; } fc->x = x; // round up to 32-bit boundary // so that in-memory data is same // layout as in-file data. if(x == 0) x = 1; if(y == 0) y = 1; if(antialias) x += -x & 3; else x += -x & 31; m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1); memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S); freememimage(m); freememimage(mc); sf->name = nil; sf->n = hi+1 - lo; sf->height = Dy(m1->r); sf->ascent = Dy(m1->r) - y0; sf->info = fc0; sf->bits = m1; return sf; }