📄 x11-draw.c
字号:
#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "error.h"#define Image IMAGE /* kernel has its own Image */#include <draw.h>#include <memdraw.h>#include <keyboard.h>#include <cursor.h>#include "screen.h"#include "x11-inc.h"/* * Allocate a Memimage with an optional pixmap backing on the X server. */Memimage*_xallocmemimage(Rectangle r, u32int chan, int pixmap){ int d, offset; Memimage *m; Xmem *xm; XImage *xi; m = _allocmemimage(r, chan); if(chan != GREY1 && chan != _x.chan) return m; if(_x.display == 0) return m; /* * For bootstrapping, don't bother storing 1x1 images * on the X server. Memimageinit needs to allocate these * and we memimageinit before we do the rest of the X stuff. * Of course, 1x1 images on the server are useless anyway. */ if(Dx(r)==1 && Dy(r)==1) return m; xm = mallocz(sizeof(Xmem), 1); if(xm == nil){ freememimage(m); return nil; } /* * Allocate backing store. */ if(chan == GREY1) d = 1; else d = _x.depth; if(pixmap != PMundef) xm->pixmap = pixmap; else xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d); /* * We want to align pixels on word boundaries. */ if(m->depth == 24) offset = r.min.x&3; else offset = r.min.x&(31/m->depth); r.min.x -= offset; assert(wordsperline(r, m->depth) <= m->width); /* * Wrap our data in an XImage structure. */ xi = XCreateImage(_x.display, _x.vis, d, ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(u32int)); if(xi == nil){ freememimage(m); if(xm->pixmap != pixmap) XFreePixmap(_x.display, xm->pixmap); return nil; } xm->xi = xi; xm->r = r; /* * Set the XImage parameters so that it looks exactly like * a Memimage -- we're using the same data. */ if(m->depth < 8 || m->depth == 24) xi->bitmap_unit = 8; else xi->bitmap_unit = m->depth; xi->byte_order = LSBFirst; xi->bitmap_bit_order = MSBFirst; xi->bitmap_pad = 32; XInitImage(xi); XFlush(_x.display); m->x = xm; return m;}/* * Replacements for libmemdraw routines. * (They've been underscored.) */Memimage*allocmemimage(Rectangle r, u32int chan){ return _xallocmemimage(r, chan, PMundef);}voidfreememimage(Memimage *m){ Xmem *xm; if(m == nil) return; xm = m->x; if(xm && m->data->ref == 1){ if(xm->xi){ xm->xi->data = nil; XFree(xm->xi); } XFreePixmap(_x.display, xm->pixmap); free(xm); m->x = nil; } _freememimage(m);}intcloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata){ int n; n = _cloadmemimage(i, r, data, ndata); if(n > 0 && i->x) _xputxdata(i, r); return n;}static int xdraw(Memdrawparam*);/* * The X acceleration doesn't fit into the standard hwaccel * model because we have the extra steps of pulling the image * data off the server and putting it back when we're done. */voidmemimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op){ Memdrawparam *par; if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil) return; /* only fetch dst data if we need it */ if((par->state&(Simplemask|Fullmask)) != (Simplemask|Fullmask)) _xgetxdata(par->dst, par->r); /* always fetch source and mask */ _xgetxdata(par->src, par->sr); _xgetxdata(par->mask, par->mr); /* now can run memimagedraw on the in-memory bits */ _memimagedraw(par); if(xdraw(par)) return; /* put bits back on x server */ _xputxdata(par->dst, par->r);}static intxdraw(Memdrawparam *par){ u32int sdval; uint m, state; Memimage *src, *dst, *mask; Point dp, mp, sp; Rectangle r; Xmem *xdst, *xmask, *xsrc; XGC gc; if(par->dst->x == nil) return 0; dst = par->dst; mask = par->mask; r = par->r; src = par->src; state = par->state; /* * If we have an opaque mask and source is one opaque pixel, * we can convert to the destination format and just XFillRectangle. */ m = Simplesrc|Fullsrc|Simplemask|Fullmask; if((state&m) == m){ _xfillcolor(dst, r, par->sdval); /* xdirtyxdata(dst, r); */ return 1; } /* * If no source alpha and an opaque mask, we can just copy * the source onto the destination. If the channels are the * same and the source is not replicated, XCopyArea works. */ m = Simplemask|Fullmask; if((state&(m|Replsrc))==m && src->chan==dst->chan && src->x){ xdst = dst->x; xsrc = src->x; dp = subpt(r.min, dst->r.min); sp = subpt(par->sr.min, src->r.min); gc = dst->chan==GREY1 ? _x.gccopy0 : _x.gccopy; XCopyArea(_x.display, xsrc->pixmap, xdst->pixmap, gc, sp.x, sp.y, Dx(r), Dy(r), dp.x, dp.y); /* xdirtyxdata(dst, r); */ return 1; } /* * If no source alpha, a 1-bit mask, and a simple source, * we can copy through the mask onto the destination. */ if(dst->x && mask->x && !(mask->flags&Frepl) && mask->chan==GREY1 && (state&Simplesrc)){ xdst = dst->x; xmask = mask->x; sdval = par->sdval; dp = subpt(r.min, dst->r.min); mp = subpt(r.min, subpt(par->mr.min, mask->r.min)); if(dst->chan == GREY1){ gc = _x.gcsimplesrc0; if(_x.gcsimplesrc0color != sdval){ XSetForeground(_x.display, gc, sdval); _x.gcsimplesrc0color = sdval; } if(_x.gcsimplesrc0pixmap != xmask->pixmap){ XSetStipple(_x.display, gc, xmask->pixmap); _x.gcsimplesrc0pixmap = xmask->pixmap; } }else{ /* this doesn't work on rob's mac? */ return 0; /* gc = _x.gcsimplesrc; if(dst->chan == CMAP8 && _x.usetable) sdval = _x.tox11[sdval]; if(_x.gcsimplesrccolor != sdval){ XSetForeground(_x.display, gc, sdval); _x.gcsimplesrccolor = sdval; } if(_x.gcsimplesrcpixmap != xmask->pixmap){ XSetStipple(_x.display, gc, xmask->pixmap); _x.gcsimplesrcpixmap = xmask->pixmap; } */ } XSetTSOrigin(_x.display, gc, mp.x, mp.y); XFillRectangle(_x.display, xdst->pixmap, gc, dp.x, dp.y, Dx(r), Dy(r)); /* xdirtyxdata(dst, r); */ return 1; } /* * Can't accelerate. */ return 0;}voidmemfillcolor(Memimage *m, u32int val){ _memfillcolor(m, val); if(m->x == nil) return; if((val & 0xFF) == 0xFF) /* full alpha */ _xfillcolor(m, m->r, _rgbatoimg(m, val)); else _xputxdata(m, m->r);}void_xfillcolor(Memimage *m, Rectangle r, u32int v){ Point p; Xmem *xm; XGC gc; xm = m->x; assert(xm != nil); /* * Set up fill context appropriately. */ if(m->chan == GREY1){ gc = _x.gcfill0; if(_x.gcfill0color != v){ XSetForeground(_x.display, gc, v); _x.gcfill0color = v; } }else{ if(m->chan == CMAP8 && _x.usetable) v = _x.tox11[v]; gc = _x.gcfill; if(_x.gcfillcolor != v){ XSetForeground(_x.display, gc, v); _x.gcfillcolor = v; } } /* * XFillRectangle takes coordinates relative to image rectangle. */ p = subpt(r.min, m->r.min); XFillRectangle(_x.display, xm->pixmap, gc, p.x, p.y, Dx(r), Dy(r));}static voidaddrect(Rectangle *rp, Rectangle r){ if(rp->min.x >= rp->max.x) *rp = r; else combinerect(rp, r);}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_xputxdata(Memimage *m, Rectangle r){ int offset, 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; if(m->depth == 24) offset = r.min.x & 3; else offset = r.min.x & (31/m->depth); 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]; }}void_xdirtyxdata(Memimage *m, Rectangle r){ Xmem *xm; xm = m->x; if(xm == nil) return; xm->dirty = 1; addrect(&xm->dirtyr, r);}intloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata){ int n; n = _loadmemimage(i, r, data, ndata); if(n > 0 && i->x) _xputxdata(i, r); return n;}intunloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata){ if(i->x) _xgetxdata(i, r); return _unloadmemimage(i, r, data, ndata);}ulongpixelbits(Memimage *m, Point p){ if(m->x) _xgetxdata(m, Rect(p.x, p.y, p.x+1, p.y+1)); return _pixelbits(m, p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -