|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <draw.h> | 
|  |  | 
|  | enum | 
|  | { | 
|  | Max = 100 | 
|  | }; | 
|  |  | 
|  | Point | 
|  | string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP, SoverD); | 
|  | } | 
|  |  | 
|  | Point | 
|  | stringop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Drawop op) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP, op); | 
|  | } | 
|  |  | 
|  | Point | 
|  | stringn(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP, SoverD); | 
|  | } | 
|  |  | 
|  | Point | 
|  | stringnop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Drawop op) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP, op); | 
|  | } | 
|  |  | 
|  | Point | 
|  | runestring(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP, SoverD); | 
|  | } | 
|  |  | 
|  | Point | 
|  | runestringop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Drawop op) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP, op); | 
|  | } | 
|  |  | 
|  | Point | 
|  | runestringn(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP, SoverD); | 
|  | } | 
|  |  | 
|  | Point | 
|  | runestringnop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Drawop op) | 
|  | { | 
|  | return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP, op); | 
|  | } | 
|  |  | 
|  | Point | 
|  | _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp, Drawop op) | 
|  | { | 
|  | int m, n, wid, max; | 
|  | ushort cbuf[Max], *c, *ec; | 
|  | uchar *b; | 
|  | char *subfontname; | 
|  | char **sptr; | 
|  | Rune **rptr; | 
|  | Font *def; | 
|  | Subfont *sf; | 
|  |  | 
|  | if(s == nil){ | 
|  | s = ""; | 
|  | sptr = nil; | 
|  | }else | 
|  | sptr = &s; | 
|  | if(r == nil){ | 
|  | r = (Rune*) L""; | 
|  | rptr = nil; | 
|  | }else | 
|  | rptr = &r; | 
|  | sf = nil; | 
|  | while((*s || *r) && len){ | 
|  | max = Max; | 
|  | if(len < max) | 
|  | max = len; | 
|  | n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname); | 
|  | if(n > 0){ | 
|  | _setdrawop(dst->display, op); | 
|  |  | 
|  | m = 47+2*n; | 
|  | if(bg) | 
|  | m += 4+2*4; | 
|  | b = bufimage(dst->display, m); | 
|  | if(b == 0){ | 
|  | fprint(2, "string: %r\n"); | 
|  | break; | 
|  | } | 
|  | if(bg) | 
|  | b[0] = 'x'; | 
|  | else | 
|  | b[0] = 's'; | 
|  | BPLONG(b+1, dst->id); | 
|  | BPLONG(b+5, src->id); | 
|  | BPLONG(b+9, f->cacheimage->id); | 
|  | BPLONG(b+13, pt.x); | 
|  | BPLONG(b+17, pt.y+f->ascent); | 
|  | BPLONG(b+21, clipr.min.x); | 
|  | BPLONG(b+25, clipr.min.y); | 
|  | BPLONG(b+29, clipr.max.x); | 
|  | BPLONG(b+33, clipr.max.y); | 
|  | BPLONG(b+37, sp.x); | 
|  | BPLONG(b+41, sp.y); | 
|  | BPSHORT(b+45, n); | 
|  | b += 47; | 
|  | if(bg){ | 
|  | BPLONG(b, bg->id); | 
|  | BPLONG(b+4, bgp.x); | 
|  | BPLONG(b+8, bgp.y); | 
|  | b += 12; | 
|  | } | 
|  | ec = &cbuf[n]; | 
|  | for(c=cbuf; c<ec; c++, b+=2) | 
|  | BPSHORT(b, *c); | 
|  | pt.x += wid; | 
|  | bgp.x += wid; | 
|  | agefont(f); | 
|  | len -= n; | 
|  | } | 
|  | if(subfontname){ | 
|  | freesubfont(sf); | 
|  | if((sf=_getsubfont(f->display, subfontname)) == 0){ | 
|  | def = f->display ? f->display->defaultfont : nil; | 
|  | if(def && f!=def) | 
|  | f = def; | 
|  | else | 
|  | break; | 
|  | } | 
|  | /* | 
|  | * must not free sf until cachechars has found it in the cache | 
|  | * and picked up its own reference. | 
|  | */ | 
|  | } | 
|  | } | 
|  | return pt; | 
|  | } |