xref: /plan9/sys/src/libdraw/string.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 
5 enum
6 {
7 	Max = 100
8 };
9 
10 Point
11 string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s)
12 {
13 	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP);
14 }
15 
16 Point
17 stringn(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len)
18 {
19 	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP);
20 }
21 
22 Point
23 runestring(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r)
24 {
25 	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP);
26 }
27 
28 Point
29 runestringn(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len)
30 {
31 	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP);
32 }
33 
34 Point
35 _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp)
36 {
37 	int m, n, wid, max;
38 	ushort cbuf[Max], *c, *ec;
39 	uchar *b;
40 	char *subfontname;
41 	char **sptr;
42 	Rune **rptr;
43 	Font *def;
44 
45 	if(s == nil){
46 		s = "";
47 		sptr = nil;
48 	}else
49 		sptr = &s;
50 	if(r == nil){
51 		r = L"";
52 		rptr = nil;
53 	}else
54 		rptr = &r;
55 	while((*s || *r) && len){
56 		max = Max;
57 		if(len < max)
58 			max = len;
59 		n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname);
60 		if(n > 0){
61 			m = 47+2*n;
62 			if(bg)
63 				m += 4+2*4;
64 			b = bufimage(dst->display, m);
65 			if(b == 0){
66 				fprint(2, "string: %r\n");
67 				break;
68 			}
69 			if(bg)
70 				b[0] = 'x';
71 			else
72 				b[0] = 's';
73 			BPLONG(b+1, dst->id);
74 			BPLONG(b+5, src->id);
75 			BPLONG(b+9, f->cacheimage->id);
76 			BPLONG(b+13, pt.x);
77 			BPLONG(b+17, pt.y+f->ascent);
78 			BPLONG(b+21, clipr.min.x);
79 			BPLONG(b+25, clipr.min.y);
80 			BPLONG(b+29, clipr.max.x);
81 			BPLONG(b+33, clipr.max.y);
82 			BPLONG(b+37, sp.x);
83 			BPLONG(b+41, sp.y);
84 			BPSHORT(b+45, n);
85 			b += 47;
86 			if(bg){
87 				BPLONG(b, bg->id);
88 				BPLONG(b+4, bgp.x);
89 				BPLONG(b+8, bgp.y);
90 				b += 12;
91 			}
92 			ec = &cbuf[n];
93 			for(c=cbuf; c<ec; c++, b+=2)
94 				BPSHORT(b, *c);
95 			pt.x += wid;
96 			bgp.x += wid;
97 			agefont(f);
98 			len -= n;
99 		}
100 		if(subfontname){
101 			if(_getsubfont(f->display, subfontname) == 0){
102 				def = f->display->defaultfont;
103 				if(def && f!=def)
104 					f = def;
105 				else
106 					break;
107 			}
108 		}
109 	}
110 	return pt;
111 }
112