static void swload(Cursor *curs) { uchar *ip, *mp; int i, j, set, clr; if(!swimg || !swmask || !swimg1 || !swmask1) return; /* * Build cursor image and mask. * Image is just the usual cursor image * but mask is a transparent alpha mask. * * The 16x16x8 memimages do not have * padding at the end of their scan lines. */ ip = byteaddr(swimg, ZP); mp = byteaddr(swmask, ZP); for(i=0; i<32; i++){ set = curs->set[i]; clr = curs->clr[i]; for(j=0x80; j; j>>=1){ *ip++ = set&j ? 0x00 : 0xFF; *mp++ = (clr|set)&j ? 0xFF : 0x00; } } swoffset = curs->offset; swvers++; memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S); memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S); }
Memimage* rot90(Memimage *m) { int line, bpp, x, y, dx, dy; ulong chan; uchar *s, *d; Memimage *w; bpp = (m->depth+7)/8; chan = m->chan; switch(chan){ case GREY1: case GREY2: case GREY4: if((w = allocmemimage(m->r, GREY8)) == nil) sysfatal("allocmemimage: %r"); memimagedraw(w, w->r, m, m->r.min, nil, ZP, S); freememimage(m); m = w; break; } dx = Dx(m->r); dy = Dy(m->r); if((w = allocmemimage(Rect(m->r.min.x, m->r.min.y, m->r.min.x+dy, m->r.min.y+dx), m->chan)) == nil) sysfatal("allocmemimage: %r"); line = w->width*sizeof(ulong); for(y=0; y<dy; y++){ s = byteaddr(m, addpt(m->r.min, Pt(0, y))); d = byteaddr(w, addpt(w->r.min, Pt(dy-y-1, 0))); for(x=0; x<dx; x++){ switch(bpp){ case 4: d[3] = s[3]; case 3: d[2] = s[2]; case 2: d[1] = s[1]; case 1: d[0] = s[0]; } s += bpp; d += line; } } freememimage(m); if(w->chan != chan){ if((m = allocmemimage(w->r, chan)) == nil) sysfatal("allocmemimage: %r"); memimagedraw(m, m->r, w, w->r.min, nil, ZP, S); freememimage(w); w = m; } return w; }
void flushmemscreen(Rectangle r) { screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP, gscreen->width*sizeof(ulong)); // Sleep(100); }
static void fillcolor(Memimage *dst, int left, int right, int y, Memimage *src, Point p) { int srcval; USED(src); srcval = p.x; p.x = left; p.y = y; memset(byteaddr(dst, p), srcval, right-left); }
Memimage* upsidedown(Memimage *m) { uchar *s, *d, *t; int w, y, dy; dy = Dy(m->r); w = m->width * sizeof(ulong); if((t = malloc(w)) == nil) sysfatal("malloc: %r"); for(y=0; y<dy/2; y++){ s = byteaddr(m, addpt(m->r.min, Pt(0, y))); d = byteaddr(m, addpt(m->r.min, Pt(0, dy-y-1))); memmove(t, d, w); memmove(d, s, w); memmove(s, t, w); } free(t); return m; }
void _xputxdata(Memimage *m, Rectangle r) { int x, y; uchar *p; Point tp, xdelta, delta; Xmem *xm; XGC gc; XImage *xi; xm = m->X; if(xm == nil) return; xi = xm->xi; gc = m->chan==GREY1 ? _x.gccopy0 : _x.gccopy; delta = subpt(r.min, m->r.min); tp = xm->r.min; /* need temporary on Digital UNIX */ xdelta = subpt(r.min, tp); if(_x.usetable && m->chan==CMAP8){ for(y=r.min.y; y<r.max.y; y++) for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++) *p = _x.tox11[*p]; } XPutImage(_x.display, xm->pixmap, gc, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r)); if(_x.usetable && m->chan==CMAP8){ for(y=r.min.y; y<r.max.y; y++) for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++) *p = _x.toplan9[*p]; } }
int unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, l; uchar *q; if(!rectinrect(r, i->r)) return -1; l = bytesperline(r, i->depth); if(ndata < l*Dy(r)) return -1; ndata = l*Dy(r); q = byteaddr(i, r.min); for(y=r.min.y; y<r.max.y; y++){ memmove(data, q, l); q += i->width*sizeof(ulong); data += l; } return ndata; }
XImage* _xgetxdata(Memimage *m, Rectangle r) { int x, y; uchar *p; Point tp, xdelta, delta; Xmem *xm; xm = m->X; if(xm == nil) return nil; if(xm->dirty == 0) return xm->xi; abort(); /* should never call this now */ r = xm->dirtyr; if(Dx(r)==0 || Dy(r)==0) return xm->xi; delta = subpt(r.min, m->r.min); tp = xm->r.min; /* need temp for Digital UNIX */ xdelta = subpt(r.min, tp); XGetSubImage(_x.display, xm->pixmap, delta.x, delta.y, Dx(r), Dy(r), AllPlanes, ZPixmap, xm->xi, xdelta.x, delta.y); if(_x.usetable && m->chan==CMAP8){ for(y=r.min.y; y<r.max.y; y++) for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++) *p = _x.toplan9[*p]; } xm->dirty = 0; xm->dirtyr = Rect(0,0,0,0); return xm->xi; }
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 _cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, bpl, c, cnt, offs; uchar mem[NMEM], *memp, *omemp, *emem, *linep, *elinep, *u, *eu; if(!rectinrect(r, i->r)) return -1; bpl = bytesperline(r, i->depth); u = data; eu = data+ndata; memp = mem; emem = mem+NMEM; y = r.min.y; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; for(;;){ if(linep == elinep){ if(++y == r.max.y) break; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; } if(u == eu){ /* buffer too small */ return -1; } c = *u++; if(c >= 128){ for(cnt=c-128+1; cnt!=0 ;--cnt){ if(u == eu){ /* buffer too small */ return -1; } if(linep == elinep){ /* phase error */ return -1; } *linep++ = *u; *memp++ = *u++; if(memp == emem) memp = mem; } } else{ if(u == eu) /* short buffer */ return -1; offs = *u++ + ((c&3)<<8)+1; if(memp-mem < offs) omemp = memp+(NMEM-offs); else omemp = memp-offs; for(cnt=(c>>2)+NMATCH; cnt!=0; --cnt){ if(linep == elinep) /* phase error */ return -1; *linep++ = *omemp; *memp++ = *omemp++; if(omemp == emem) omemp = mem; if(memp == emem) memp = mem; } } } return u-data; }
/* * Wordaddr is deprecated. */ ulong* wordaddr(Memimage *i, Point p) { return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1)); }
static void resample(Memimage *dst, Rectangle r, Memimage *src, Rectangle sr) { Point sp, dp; Point _sp, qp; Point ssize, dsize; uchar *pdst0, *pdst, *psrc0, *psrc; ulong s00, s01, s10, s11; int tx, ty, bpp, bpl; ssize = subpt(subpt(sr.max, sr.min), Pt(1,1)); dsize = subpt(subpt(r.max, r.min), Pt(1,1)); pdst0 = byteaddr(dst, r.min); bpp = src->depth/8; bpl = src->width*sizeof(int); qp = Pt(0, 0); if(dsize.x > 0) qp.x = (ssize.x<<12)/dsize.x; if(dsize.y > 0) qp.y = (ssize.y<<12)/dsize.y; _sp.y = sr.min.y<<12; for(dp.y=0; dp.y<=dsize.y; dp.y++){ sp.y = _sp.y>>12; ty = _sp.y&0xFFF; pdst = pdst0; sp.x = sr.min.x; psrc0 = byteaddr(src, sp); _sp.x = 0; for(dp.x=0; dp.x<=dsize.x; dp.x++){ sp.x = _sp.x>>12; tx = _sp.x&0xFFF; psrc = psrc0 + sp.x*bpp; s00 = (0x1000-tx)*(0x1000-ty); s01 = tx*(0x1000-ty); s10 = (0x1000-tx)*ty; s11 = tx*ty; switch(bpp){ case 4: pdst[3] = (s11*psrc[bpl+bpp+3] + s10*psrc[bpl+3] + s01*psrc[bpp+3] + s00*psrc[3]) >>24; case 3: pdst[2] = (s11*psrc[bpl+bpp+2] + s10*psrc[bpl+2] + s01*psrc[bpp+2] + s00*psrc[2]) >>24; pdst[1] = (s11*psrc[bpl+bpp+1] + s10*psrc[bpl+1] + s01*psrc[bpp+1] + s00*psrc[1]) >>24; case 1: pdst[0] = (s11*psrc[bpl+bpp] + s10*psrc[bpl] + s01*psrc[bpp] + s00*psrc[0]) >>24; } pdst += bpp; _sp.x += qp.x; } pdst0 += dst->width*sizeof(int); _sp.y += qp.y; } }
static void xread(Req *r) { int i, size, height, ascent; vlong path; Fmt fmt; XFont *f; char *data; Memsubfont *sf; Memimage *m; path = r->fid->qid.path; switch(QTYPE(path)) { case Qroot: dirread9p(r, rootgen, nil); break; case Qfontdir: dirread9p(r, fontgen, r->fid); break; case Qsizedir: dirread9p(r, sizegen, r->fid); break; case Qfontfile: fmtstrinit(&fmt); f = &xfont[QFONT(path)]; load(f); if(f->unit == 0 && f->loadheight == nil) { readstr(r, "font missing\n"); break; } height = 0; ascent = 0; if(f->unit > 0) { height = f->height * (int)QSIZE(path)/f->unit + 0.99999999; ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999); } if(f->loadheight != nil) f->loadheight(f, QSIZE(path), &height, &ascent); fmtprint(&fmt, "%11d %11d\n", height, ascent); for(i=0; i<nelem(f->range); i++) { if(f->range[i] == 0) continue; fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", i*SubfontSize, ((i+1)*SubfontSize) - 1, i*SubfontSize); } data = fmtstrflush(&fmt); readstr(r, data); free(data); break; case Qsubfontfile: f = &xfont[QFONT(path)]; load(f); if(r->fid->aux == nil) { r->fid->aux = mksubfont(f, f->name, QRANGE(path)*SubfontSize, ((QRANGE(path)+1)*SubfontSize)-1, QSIZE(path), QANTIALIAS(path)); if(r->fid->aux == nil) { responderrstr(r); return; } } sf = r->fid->aux; m = sf->bits; if(r->ifcall.offset < 5*12) { char *chan; if(QANTIALIAS(path)) chan = "k8"; else chan = "k1"; data = smprint("%11s %11d %11d %11d %11d ", chan, m->r.min.x, m->r.min.y, m->r.max.x, m->r.max.y); readstr(r, data); free(data); break; } r->ifcall.offset -= 5*12; size = bytesperline(m->r, chantodepth(m->chan)) * Dy(m->r); if(r->ifcall.offset < size) { readbuf(r, byteaddr(m, m->r.min), size); break; } r->ifcall.offset -= size; data = emalloc9p(3*12+6*(sf->n+1)); sprint(data, "%11d %11d %11d ", sf->n, sf->height, sf->ascent); packinfo(sf->info, (uchar*)data+3*12, sf->n); readbuf(r, data, 3*12+6*(sf->n+1)); free(data); break; } respond(r, nil); }
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; }