]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ttfrender.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / ttfrender.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 #include <ttf.h>
6 #include <ctype.h>
7
8 void
9 elidenl(char **sp, int *np)
10 {
11         char *s, *e, *t;
12         int nl;
13         
14         s = t = *sp;
15         e = *sp + *np;
16         for(; s < e; s++){
17                 if(isspace(*s)){
18                         nl = 0;
19                         do
20                                 nl += *s == '\n';
21                         while(++s < e && isspace(*s));
22                         if(nl <= 1)
23                                 *t++ = ' ';
24                         else while(nl-- > 0)
25                                 *t++ = '\n';
26                         if(s == e) break;
27                 }
28                 *t++ = *s;
29         }
30 }
31
32 int
33 readtext(char *fn, char **sp, int newline)
34 {
35         int fd, n, a, rc;
36         char *s;
37         enum {B = 4096};
38         
39         fd = open(fn, OREAD);
40         if(fd < 0) sysfatal("open: %r");
41         s = nil;
42         n = 0;
43         a = 0;
44         for(;;){
45                 if(n + B > a)
46                         s = realloc(s, a += B);
47                 if(s == nil) sysfatal("realloc: %r");
48                 rc = read(fd, &s[n], B);
49                 if(rc < 0) sysfatal("read: %r");
50                 if(rc == 0) break;
51                 n += rc;
52         }
53         if(newline)
54                 elidenl(&s, &n);
55         s = realloc(s, n);
56         if(s == nil) sysfatal("realloc: %r");
57         *sp = s;
58         return n;
59 }
60
61 void
62 usage(void)
63 {
64         fprint(2, "usage: %s [ -lrjn ] [ -s scale ] [ -w width ] [ -h height ] [ -p ppem ] font [ text ]\n", argv0);
65         exits("usage");
66 }
67
68 int
69 number(char *s)
70 {
71         char *p;
72         int n;
73         
74         n = strtol(s, &p, 0);
75         if(p == s || *p != 0 || n <= 0)
76                 usage();
77         return n;       
78 }
79
80 TTBitmap *
81 scaledown(TTBitmap *b, int scale)
82 {
83         TTBitmap *a;
84         int i, j;
85         
86         a = ttfnewbitmap(b->width / scale * 8, b->height / scale);
87         if(a == nil) sysfatal("ttfnewbitmap: %r");
88         for(j = 0; j < b->height; j++)
89                 for(i = 0; i < b->width; i++){
90                         if((b->bit[j * b->stride + (i>>3)] >> 7 - (i & 7) & 1) != 0)
91                                 a->bit[j/scale * a->stride + i/scale]++;
92                         if(j % scale == scale - 1 && i % scale == scale - 1)
93                                 a->bit[j/scale * a->stride + i/scale] = ~((a->bit[j/scale * a->stride + i/scale] * 255 + scale * scale / 2) / (scale * scale));
94                 }
95         return a;
96 }
97
98 void
99 cropwrite(TTBitmap *b)
100 {
101         int l, r, u, d, i;
102         
103         l = 0;
104         r = b->stride;
105         u = 0;
106         d = b->height;
107         for(; l < r; l++)
108                 for(i = u; i < d; i++)
109                         if(b->bit[i * b->stride + l] != 0xff)
110                                 goto right;
111 right:
112         for(; l < r; r--)
113                 for(i = u; i < d; i++)
114                         if(b->bit[i * b->stride + r - 1] != 0xff)
115                                 goto up;
116 up:
117         for(; u < d; u++)
118                 for(i = l; i < r; i++)
119                         if(b->bit[u * b->stride + i] != 0xff)
120                                 goto down;
121 down:
122         for(; u < d; d--)
123                 for(i = l; i < r; i++)
124                         if(b->bit[(d - 1) * b->stride + i] != 0xff)
125                                 goto out;
126 out:
127         print("%11s %11d %11d %11d %11d ", "k8", 0, 0, r - l, d - u);
128         for(i = u; i < d; i++)
129                 write(1, b->bit + i * b->stride + l, r - l);
130
131 }
132
133 void
134 main(int argc, char **argv)
135 {
136         static int flags, scale, width, height, ppem, newline, crop;
137         char *font, *txtfn, *txt;
138         int txtn;
139         TTFont *f;
140         TTBitmap *b;
141         TTBitmap *d;
142
143         width = 640;
144         height = 480;
145         ppem = 18;
146         scale = 1;
147         ARGBEGIN {
148         case 'l': break;
149         case 'r': flags |= TTFRALIGN; break;
150         case 'c': flags |= TTFCENTER; break;
151         case 'j': flags |= TTFJUSTIFY; break;
152         case 'p': ppem = number(EARGF(usage())); break;
153         case 's': scale = number(EARGF(usage())); break;
154         case 'w': width = number(EARGF(usage())); break;
155         case 'h': height = number(EARGF(usage())); break;
156         case 'n': newline++; break;
157         case 'C': crop++; break;
158         } ARGEND;
159         if((uint)(argc - 1) > 1) usage();
160         font = argv[0];
161         txtfn = argc > 1 ? argv[1] : "/fd/0";
162         txtn = readtext(txtfn, &txt, newline);
163         f = ttfopen(font, ppem * scale, 0);
164         if(f == nil) sysfatal("ttfopen: %r");
165         b = ttfrender(f, txt, txt + txtn, width * scale, height * scale, flags, nil);
166         if(b == nil) sysfatal("ttfrender: %r");
167         d = scaledown(b, scale);
168         if(crop) cropwrite(d);
169         else{
170                 print("%11s %11d %11d %11d %11d ", "k8", 0, 0, d->width/8, d->height);
171                 write(1, d->bit, d->stride * d->height);
172         }
173 }