/* * Just free the data structures, don't do graphics */ void memlfree(Memimage *i) { Memlayer *l; l = i->layer; freememimage(l->save); free(l); freememimage(i); }
int memlsetrefresh(Memimage *i, Refreshfn fn, void *ptr) { Memlayer *l; l = i->layer; if(l->refreshfn!=0 && fn!=0) { /* just change functions */ l->refreshfn = fn; l->refreshptr = ptr; return 1; } if(l->refreshfn == 0) { /* is using backup image; just free it */ freememimage(l->save); l->save = nil; l->refreshfn = fn; l->refreshptr = ptr; return 1; } l->save = allocmemimage(i->r, i->chan); if(l->save == nil) return 0; /* easiest way is just to update the entire save area */ l->refreshfn(i, i->r, l->refreshptr); l->refreshfn = 0; l->refreshptr = nil; return 1; }
static void freecimage(Cimage *ci) { Cimage *ci1; qlock(&cimagelock); if(decref(ci) == 0){ if(ci->i) freeimage(ci->i); else if(ci->mi) freememimage(ci->mi); urlfree(ci->url); ci1 = cimages; if(ci1 == ci) cimages = ci->next; else{ while(ci1){ if(ci1->next == ci){ ci1->next = ci->next; break; } ci1 = ci1->next; } } free(ci); } qunlock(&cimagelock); }
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); }
void main(int argc, char *argv[]) { Biobuf bout; Memimage *i; int fd; char *err, *filename; ImageInfo II; ARGBEGIN{ case 'c': II.comment = ARGF(); if(II.comment == nil) usage(); II.fields_set |= II_COMMENT; break; case 'g': II.gamma = atof(ARGF()); if(II.gamma == 0.) usage(); II.fields_set |= II_GAMMA; break; case 't': break; default: usage(); }ARGEND if(Binit(&bout, 1, OWRITE) < 0) sysfatal("Binit failed: %r"); memimageinit(); if(argc == 0){ fd = 0; filename = "<stdin>"; }else{ fd = open(argv[0], OREAD); if(fd < 0) sysfatal("can't open %s: %r", argv[0]); filename = argv[0]; } i = readmemimage(fd); if(i == nil) sysfatal("can't readimage %s: %r", filename); close(fd); err = memwritepng(&bout, i, &II); freememimage(i); if(err != nil) fprint(2, "topng: %s\n", err); exits(err); }
Memsubfont* openmemsubfont(char *name) { Memsubfont *sf; Memimage *i; Fontchar *fc; int fd, n; char hdr[3*12+4+1]; uchar *p; fd = open(name, OREAD); if(fd < 0) return nil; p = nil; i = readmemimage(fd); if(i == nil) goto Err; if(readn(fd, hdr, 3*12) != 3*12){ werrstr("openmemsubfont: header read error: %r"); goto Err; } n = atoi(hdr); if(n <= 0 || n > 0x7fff){ werrstr("openmemsubfont: bad fontchar count %d", n); goto Err; } p = malloc(6*(n+1)); if(p == nil) goto Err; if(readn(fd, p, 6*(n+1)) != 6*(n+1)){ werrstr("openmemsubfont: fontchar read error: %r"); goto Err; } fc = malloc(sizeof(Fontchar)*(n+1)); if(fc == nil) goto Err; _unpackinfo(fc, p, n); sf = allocmemsubfont(name, n, atoi(hdr+12), atoi(hdr+24), fc, i); if(sf == nil){ free(fc); goto Err; } close(fd); free(p); return sf; Err: close(fd); free(p); freememimage(i); return nil; }
static void xdestroyfid(Fid *fid) { Memsubfont *sf; sf = fid->aux; if(sf == nil) return; freememimage(sf->bits); free(sf->info); free(sf); fid->aux = nil; }
int memunload(Memimage *src, Rectangle r, uint8_t *data, int n) { Memimage *tmp; Memlayer *dl; Rectangle lr; int dx; Top: dl = src->layer; if(dl == nil) return unloadmemimage(src, r, data, n); /* * Convert to screen coordinates. */ lr = r; r.min.x += dl->delta.x; r.min.y += dl->delta.y; r.max.x += dl->delta.x; r.max.y += dl->delta.y; dx = dl->delta.x&(7/src->depth); if(dl->clear && dx==0){ src = dl->screen->image; goto Top; } /* * src is an obscured layer or data is unaligned */ if(dl->save && dx==0){ if(dl->refreshfn != nil) return -1; /* can't unload window if it's not Refbackup */ if(n > 0) memlhide(src, r); n = unloadmemimage(dl->save, lr, data, n); return n; } tmp = allocmemimage(lr, src->chan); if(tmp == nil) return -1; memdraw(tmp, lr, src, lr.min, nil, lr.min, S); n = unloadmemimage(tmp, lr, data, n); freememimage(tmp); return n; }
void getimage(Cimage *ci, Rune *altr) { Rectangle r; Memimage *mi; Image *i, *i2; char buf[128]; uchar *bits; int nbits; mi = ci->mi; if(mi == nil) { snprint(buf, sizeof(buf), "[%S]", altr ? altr : L"IMG"); r.min = Pt(0, 0); r.max.x = 2*Space + stringwidth(font, buf); r.max.y = 2*Space + font->height; ci->i = eallocimage(display, r, GREY1, 1, DBlack); r.min.x += Space; r.min.y += Space; string(ci->i, r.min, display->white, ZP, font, buf); return; } nbits = bytesperline(mi->r, mi->depth)*Dy(mi->r); bits = emalloc(nbits); unloadmemimage(mi, mi->r, bits, nbits); /* /* get rid of alpha channel from transparent gif * / if(mi->depth == 16){ for(y=1; y<nbits; y+=2) bits[y>>1] = bits[y]; } */ i = eallocimage(display, mi->r, mi->chan, 0, DNofill); loadimage(i, i->r, bits, nbits); i2 = eallocimage(display, i->r, RGB24, 1, DNofill); draw(i2, i2->r, display->black, nil, ZP); draw(i2, i2->r, i, nil, i->r.min); free(bits); freememimage(mi); freeimage(i); ci->i = i2; ci->mi = nil; }
static void screenwin(void) { Point p, q; char *greet; Memimage *orange; Rectangle r; memsetchan(gscreen, RGB16); back = memwhite; conscol = memblack; orange = allocmemimage(Rect(0,0,1,1), RGB16); orange->flags |= Frepl; orange->clipr = gscreen->r; orange->data->bdata[0] = 0x40; orange->data->bdata[1] = 0xfd; w = memdefont->info[' '].width; h = memdefont->height; r = insetrect(gscreen->r, 4); memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S); window = insetrect(r, 4); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP, S); freememimage(orange); 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); flushmemscreen(r); window.min.y += h+6; curpos = window.min; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; }
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(); }
Memsubfont* getmemdefont(void) { char *hdr, *p; int n; Fontchar *fc; Memsubfont *f; int ld; Rectangle r; Memdata *md; Memimage *i; /* * make sure data is word-aligned. this is true with Plan 9 compilers * but not in general. the byte order is right because the data is * declared as char*, not u32int*. */ p = (char*)defontdata; n = (uintptr)p & 3; if(n != 0){ memmove(p+(4-n), p, sizeofdefont-n); p += 4-n; } ld = atoi(p+0*12); r.min.x = atoi(p+1*12); r.min.y = atoi(p+2*12); r.max.x = atoi(p+3*12); r.max.y = atoi(p+4*12); md = mallocz(sizeof(Memdata), 1); if(md == nil) return nil; p += 5*12; md->base = nil; /* so freememimage doesn't free p */ md->bdata = (uchar*)p; /* ick */ md->ref = 1; md->allocd = 1; /* so freememimage does free md */ i = allocmemimaged(r, drawld2chan[ld], md, nil); if(i == nil){ free(md); return nil; } hdr = p+Dy(r)*i->width*sizeof(u32int); n = atoi(hdr); p = hdr+3*12; fc = malloc(sizeof(Fontchar)*(n+1)); if(fc == 0){ freememimage(i); return 0; } _unpackinfo(fc, (uchar*)p, n); f = allocmemsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i); if(f == 0){ freememimage(i); free(fc); return 0; } return f; }
static int xgraph(HConnect *c) { char *name; Hio *hout; Memimage *m; int dotext; Graph g; Arg arg; char *graph, *a; name = hargstr(c, "arg", ""); if((arg.index = findname(name)) == -1 && strcmp(name, "*") != 0){ werrstr("unknown name %s", name); goto error; } a = hargstr(c, "arg2", ""); if(a[0] && (arg.index2 = findname(a)) == -1){ werrstr("unknown name %s", a); goto error; } g.arg = &arg; g.t0 = hargint(c, "t0", -120); g.t1 = hargint(c, "t1", 0); g.min = hargint(c, "min", -1); g.max = hargint(c, "max", -1); g.wid = hargint(c, "wid", -1); g.ht = hargint(c, "ht", -1); dotext = hargstr(c, "text", "")[0] != 0; g.fill = hargint(c, "fill", -1); graph = hargstr(c, "graph", "raw"); if(strcmp(graph, "raw") == 0) g.fn = rawgraph; else if(strcmp(graph, "diskbw") == 0) g.fn = diskgraph; else if(strcmp(graph, "iobw") == 0) g.fn = iograph; else if(strcmp(graph, "netbw") == 0) g.fn = netgraph; else if(strcmp(graph, "diff") == 0) g.fn = diffgraph; else if(strcmp(graph, "pct") == 0) g.fn = pctgraph; else if(strcmp(graph, "pctdiff") == 0) g.fn = pctdiffgraph; else if(strcmp(graph, "divdiff") == 0) g.fn = divdiffgraph; else{ werrstr("unknown graph %s", graph); goto error; } if(dotext){ hsettype(c, "text/plain"); dotextbin(&c->hout, &g); hflush(&c->hout); return 0; } m = statgraph(&g); if(m == nil) goto error; if(hsettype(c, "image/png") < 0) return -1; hout = &c->hout; writepng(hout, m); qlock(&memdrawlock); freememimage(m); qunlock(&memdrawlock); hflush(hout); return 0; error: return herror(c); }
/* * Place i so i->r.min = log, i->layer->screenr.min == scr. */ int memlorigin(Memimage *i, Point log, Point scr) { Memlayer *l; Memscreen *s; Memimage *t, *shad, *nsave; Rectangle x, newr, oldr; Point delta; int overlap, eqlog, eqscr, wasclear; l = i->layer; s = l->screen; oldr = l->screenr; newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr)); eqscr = eqpt(scr, oldr.min); eqlog = eqpt(log, i->r.min); if(eqscr && eqlog) return 0; nsave = nil; if(eqlog==0 && l->save!=nil){ nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan); if(nsave == nil) return -1; } /* * Bring it to front and move logical coordinate system. */ memltofront(i); wasclear = l->clear; if(nsave){ if(!wasclear) memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S); freememimage(l->save); l->save = nsave; } delta = subpt(log, i->r.min); i->r = rectaddpt(i->r, delta); i->clipr = rectaddpt(i->clipr, delta); l->delta = subpt(l->screenr.min, i->r.min); if(eqscr) return 0; /* * To clean up old position, make a shadow window there, don't paint it, * push it behind this one, and (later) delete it. Because the refresh function * for this fake window is a no-op, this will cause no graphics action except * to restore the background and expose the windows previously hidden. */ shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill); if(shad == nil) return -1; s->frontmost = i; if(s->rearmost == i) s->rearmost = shad; else l->rear->layer->front = shad; shad->layer->front = i; shad->layer->rear = l->rear; l->rear = shad; l->front = nil; shad->layer->clear = 0; /* * Shadow is now holding down the fort at the old position. * Move the window and hide things obscured by new position. */ for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){ x = newr; overlap = rectclip(&x, t->layer->screenr); if(overlap){ memlhide(t, x); t->layer->clear = 0; } } l->screenr = newr; l->delta = subpt(scr, i->r.min); l->clear = rectinrect(newr, l->screen->image->clipr); /* * Everything's covered. Copy to new position and delete shadow window. */ if(wasclear) memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S); else memlexpose(i, newr); memldelete(shad); return 1; }
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); }
void imagebits(Biobuf *ioutb, Memimage *im) { int spb; int bitoff; int j, n, n4, i, bpl, nrest; int lsf; uchar c85[6], *data, *src, *dst; Memimage *tmp; Rectangle r; tmp = nil; if (debug) fprint(2, "imagebits, r=%d %d %d %d, depth=%d\n", im->r.min.x, im->r.min.y, im->r.max.x, im->r.max.y, im->depth); width = Dx(im->r); height = Dy(im->r); bps = im->depth; /* # bits per sample */ bitoff = 0; /* # bit offset of beginning sample within first byte */ if (bps < 8) { spb = 8 / bps; bitoff = (im->r.min.x % spb) * bps; } if (bitoff != 0) { /* # Postscript image wants beginning of line at beginning of byte */ r = im->r; r.min.x -= bitoff/im->depth; r.max.x -= bitoff/im->depth; tmp = allocmemimage(r, im->chan); if(tmp == nil){ fprint(2, "p9bitpost: allocmemimage failed: %r\n"); exits("alloc"); } memimagedraw(tmp, r, im, im->r.min, nil, ZP, S); im = tmp; } lsf = 0; /* compact data to remove word-boundary padding */ bpl = bytesperline(im->r, im->depth); n = bpl*Dy(im->r); data = malloc(n); if(data == nil){ fprint(2, "p9bitpost: malloc failed: %r\n"); exits("malloc"); } for(i=0; i<Dy(im->r); i++){ /* memmove(data+bpl*i, byteaddr(im, Pt(im->r.min.x, im->r.min.y+i)), bpl); with inversion */ dst = data+bpl*i; src = byteaddr(im, Pt(im->r.min.x, im->r.min.y+i)); for(j=0; j<bpl; j++) *dst++ = 255 - *src++; } n4 = (n / 4) * 4; for (i = 0; i < n4; i += 4){ cmap2ascii85(data+i, c85); lsf += strlen((char *)c85); Bprint(ioutb, "%s", (char *)c85); if (lsf > 74) { Bprint(ioutb, "\n"); lsf = 0; } } nrest = n - n4; if (nrest != 0) { uchar foo[4]; for (i=0; i<nrest; i++) foo[i] = data[n4+i]; for (i=nrest; i<4; i++) foo[i] = '\0'; cmap2ascii85(foo, c85); if (strcmp((char *)c85, "z") == 0 ) strcpy((char *)c85, "!!!!!"); Bprint(ioutb, "%.*s", nrest+1, (char *)c85); } Bprint(ioutb, "\n~>"); Bprint(ioutb, "\n"); freememimage(tmp); }
int image2psfile(int fd, Memimage *im, int dpi) { Rectangle r; Rectangle bbox; int e; int xmargin = 36; int ymargin = 36; double paperaspectratio; double imageaspectratio; Biobuf ioutb; Memimage *tmp; if(im->depth >= 8 && im->chan != CMAP8 && im->chan != GREY8){ /* * the postscript libraries can only handle [1248]-bit grey, 8-bit cmap, * and 24-bit color, so convert. */ tmp = allocmemimage(im->r, strtochan("b8g8r8")); if(tmp == nil) return 1; memimagedraw(tmp, tmp->r, im, im->r.min, nil, ZP, S); freememimage(im); im = tmp; } Binit(&ioutb, fd, OWRITE); r = im->r; width = Dx(r); height = Dy(r); imageaspectratio = (double) width / (double) height; if (landscape) { paperaspectratio = ((double)paperlength - (ymargin * 2)) / ((double)paperwidth - (xmargin * 2)); if (dpi > 0) { iwidth = width * 72 / dpi; iheight = height * 72 / dpi; } else if (imageaspectratio > paperaspectratio) { iwidth = paperlength - (ymargin * 2); iheight = iwidth / imageaspectratio; } else { iheight = paperwidth - (xmargin * 2); iwidth = iheight * imageaspectratio; } xstart = paperwidth - xmargin - (iheight * ymagnification); ystart = paperlength - ymargin; rotation = -90; } else { paperaspectratio = ((double)paperwidth - (xmargin * 2)) / ((double)paperlength - (ymargin * 2)); if (dpi > 0) { iwidth = width * 72 / dpi; iheight = height * 72 / dpi; } else if (imageaspectratio > paperaspectratio) { iwidth = paperwidth - (xmargin * 2); iheight = iwidth / imageaspectratio; } else { iheight = paperlength - (ymargin * 2); iwidth = iheight * imageaspectratio; } xstart = xmargin; ystart = paperlength - ymargin - (iheight * ymagnification); rotation = 0; } bbox = Rect(xstart,ystart,xstart+iwidth,ystart+iheight); e = preamble(&ioutb, bbox); if(e != 0) return e; Bprint(&ioutb, "%%%%Page: 1\n%%%%BeginPageSetup\n"); Bprint(&ioutb, "/pgsave save def\n"); Bprint(&ioutb, "%%%%EndPageSetup\n"); bps = im->depth; Bprint(&ioutb, "%d 0 %d %d %d %d %d %d %s doimage\n", iheight, iwidth, ystart, xstart, height, width, bps, im->flags&Fgrey ? "true" : "false"); imagebits(&ioutb, im); Bprint(&ioutb, "pgsave restore\nshowpage\n"); e = trailer(&ioutb, 1); if(e != 0) return e; Bterm(&ioutb); return 0; }
void main(int argc, char *argv[]) { Biobuf bout; Memimage *i, *ni; int fd, j, dt, trans, loop; char buf[256]; char *err, *comment, *s; comment = nil; dt = -1; trans = -1; loop = UNSET; ARGBEGIN{ case 'l': s = ARGF(); if(s==nil || (!isdigit(s[0]) && s[0]!='-')) usage(); loop = atoi(s); break; case 'c': comment = ARGF(); if(comment == nil) usage(); break; case 'd': s = ARGF(); if(s==nil || !isdigit(s[0])) usage(); dt = atoi(s); break; case 't': s = ARGF(); if(s==nil || !isdigit(s[0])) usage(); trans = atoi(s); if(trans > 255) usage(); break; default: usage(); }ARGEND if(Binit(&bout, 1, OWRITE) < 0) sysfatal("Binit failed: %r"); memimageinit(); err = nil; if(argc == 0){ i = readmemimage(0); if(i == nil) sysfatal("reading input: %r"); ni = memonechan(i); if(ni == nil) sysfatal("converting image to RGBV: %r"); if(i != ni){ freememimage(i); i = ni; } err = memstartgif(&bout, i, -1); if(err == nil){ if(comment) err = memwritegif(&bout, i, comment, dt, trans); else{ snprint(buf, sizeof buf, "Converted by Plan 9 from <stdin>"); err = memwritegif(&bout, i, buf, dt, trans); } } }else{ if(loop == UNSET){ if(argc == 1) loop = -1; /* no loop for single image */ else loop = 0; /* the default case: 0 means infinite loop */ } for(j=0; j<argc; j++){ if(argv[j][0] == '-' && argv[j][1]=='d'){ /* time change */ if(argv[j][2] == '\0'){ s = argv[++j]; if(j == argc) usage(); }else s = &argv[j][2]; if(!isdigit(s[0])) usage(); dt = atoi(s); if(j == argc-1) /* last argument must be file */ usage(); continue; } fd = open(argv[j], OREAD); if(fd < 0) sysfatal("can't open %s: %r", argv[j]); i = readmemimage(fd); if(i == nil) sysfatal("can't readimage %s: %r", argv[j]); close(fd); ni = memonechan(i); if(ni == nil) sysfatal("converting image to RGBV: %r"); if(i != ni){ freememimage(i); i = ni; } if(j == 0){ err = memstartgif(&bout, i, loop); if(err != nil) break; } if(comment) err = memwritegif(&bout, i, comment, dt, trans); else{ snprint(buf, sizeof buf, "Converted by Plan 9 from %s", argv[j]); err = memwritegif(&bout, i, buf, dt, trans); } if(err != nil) break; freememimage(i); comment = nil; } } memendgif(&bout); if(err != nil) fprint(2, "togif: %s\n", err); exits(err); }
void main(int argc, char **argv) { int fd, xsize, ysize; Memimage *im, *nim; ulong ochan, tchan; xsize = ysize = 0; ARGBEGIN{ case 'a': xsize = ysize = getsize(EARGF(usage())); break; case 'x': xsize = getsize(EARGF(usage())); break; case 'y': ysize = getsize(EARGF(usage())); break; default: usage(); }ARGEND fd = 0; if(*argv){ fd = open(*argv, OREAD); if(fd < 0) sysfatal("open: %r"); } memimageinit(); if((im = readmemimage(fd)) == nil) sysfatal("readmemimage: %r"); if(xsize & PERCENT) xsize = ((xsize & ~PERCENT) * Dx(im->r)) / 100; if(ysize & PERCENT) ysize = ((ysize & ~PERCENT) * Dy(im->r)) / 100; if(xsize || ysize){ if(ysize == 0) ysize = (xsize * Dy(im->r)) / Dx(im->r); if(xsize == 0) xsize = (ysize * Dx(im->r)) / Dy(im->r); ochan = im->chan; switch(ochan){ default: for(tchan = ochan; tchan; tchan >>= 8) if(TYPE(tchan) == CAlpha){ tchan = RGBA32; break; } if(tchan == 0) tchan = RGB24; break; case GREY8: case RGB24: case RGBA32: case ARGB32: case XRGB32: tchan = ochan; break; case GREY1: case GREY2: case GREY4: tchan = GREY8; break; } if(tchan != ochan){ if((nim = allocmemimage(im->r, tchan)) == nil) sysfatal("allocimage: %r"); memimagedraw(nim, nim->r, im, im->r.min, nil, ZP, S); freememimage(im); im = nim; } if((nim = allocmemimage( Rect(im->r.min.x, im->r.min.y, im->r.min.x+xsize, im->r.min.y+ysize), tchan)) == nil) sysfatal("allocmemimage: %r"); resample(nim, nim->r, im, im->r); freememimage(im); im = nim; if(tchan != ochan){ if((im = allocmemimage(nim->r, ochan)) == nil) sysfatal("allocimage: %r"); memimagedraw(im, im->r, nim, nim->r.min, nil, ZP, S); freememimage(nim); } } if(writememimage(1, im) < 0) sysfatal("writememimage: %r"); exits(0); }
/* * 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); }
int screensize(int x, int y, int z, uint32_t chan) { Proc *up = externup(); VGAscr *scr; void *oldsoft; lock(&vgascreenlock); if(waserror()){ unlock(&vgascreenlock); nexterror(); } memimageinit(); scr = &vgascreen[0]; oldsoft = softscreen; if(scr->paddr == 0){ int width = (x*z)/BI2WD; void *p; p = malloc(width*BY2WD*y); if(p == nil) error("no memory for vga soft screen"); gscreendata.bdata = softscreen = p; if(scr->dev && scr->dev->page){ scr->vaddr = KADDR(VGAMEM()); scr->apsize = 1<<16; } scr->useflush = 1; } else{ gscreendata.bdata = scr->vaddr; scr->useflush = scr->dev && scr->dev->flush; } scr->gscreen = nil; if(gscreen) freememimage(gscreen); gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); if(gscreen == nil) error("no memory for vga memimage"); vgaimageinit(chan); scr->palettedepth = 6; /* default */ scr->gscreendata = &gscreendata; scr->memdefont = getmemdefont(); scr->gscreen = gscreen; physgscreenr = gscreen->r; unlock(&vgascreenlock); poperror(); if(oldsoft) free(oldsoft); memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S); flushmemscreen(gscreen->r); if(didswcursorinit) swcursorinit(); drawcmap(); return 0; }
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; }