History

split

Sigrid Haflínudóttir committed 6 years ago

Commit 2c8b32e1 parent 3e3d9c65 files · +365 −343Browse files

Unified · Split

5 files
  1. mkfile +1 −0
  2. pt.c +304 −0
  3. pt.h +20 −0
  4. pt_private.h +18 −0
  5. test.c +22 −343
mkfile+1−0
@@ -7,6 +7,7 @@ HFILES=stb_truetype.h · 6 unmodified lines
77 UPDATE=$HFILES
88 OFILES=\
99 nanosec.$O\
10+ pt.$O\
1011 test.$O\
1112
1213 default:V: all
pt.c+304−0
@@ -0,0 +1,304 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <draw.h>
4+#include <keyboard.h>
5+#include <memdraw.h>
6+#include <mouse.h>
7+#include <thread.h>
8+#include "pt.h"
9+
10+uvlong nanosec(void);
11+
12+#define MAX(a,b) ((a)>=(b)?(a):(b))
13+
14+#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
15+
16+static const uchar mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
17+
18+static int
19+utf16to8(uchar *o, int osz, const uchar *s, int sz)
20+{
21+ int i, be, c, c2, wr, j;
22+
23+ i = 0;
24+ be = 1;
25+ if(s[0] == 0xfe && s[1] == 0xff)
26+ i += 2;
27+ else if(s[0] == 0xff && s[1] == 0xfe){
28+ be = 0;
29+ i += 2;
30+ }
31+
32+ for(; i < sz-1 && osz > 1;){
33+ c = rchr(&s[i]);
34+ i += 2;
35+ if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
36+ c2 = rchr(&s[i]);
37+ if(c2 >= 0xdc00 && c2 <= 0xdfff){
38+ c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
39+ i += 2;
40+ }else
41+ return -1;
42+ }else if(c >= 0xdc00 && c <= 0xdfff)
43+ return -1;
44+
45+ if(c < 0x80)
46+ wr = 1;
47+ else if(c < 0x800)
48+ wr = 2;
49+ else if(c < 0x10000)
50+ wr = 3;
51+ else
52+ wr = 4;
53+
54+ osz -= wr;
55+ if(osz < 1)
56+ break;
57+
58+ o += wr;
59+ for(j = wr; j > 1; j--){
60+ *(--o) = (c & 0xbf) | 0x80;
61+ c >>= 6;
62+ }
63+ *(--o) = c | mark[wr];
64+ o += wr;
65+ }
66+
67+ *o = 0;
68+ return i;
69+}
70+
71+#define STB_TRUETYPE_IMPLEMENTATION
72+#define STBTT_ifloor(x) ((int)floor(x))
73+#define STBTT_iceil(x) ((int)ceil(x))
74+#define STBTT_sqrt(x) sqrt(x)
75+#define STBTT_pow(x,y) pow(x,y)
76+#define STBTT_fmod(x,y) fmod(x,y)
77+#define STBTT_cos(x) cos(x)
78+#define STBTT_acos(x) acos(x)
79+#define STBTT_fabs(x) fabs(x)
80+#define STBTT_malloc(x,u) ((void)(u),malloc(x))
81+#define STBTT_free(x,u) ((void)(u),free(x))
82+#define STBTT_assert(x) assert(x)
83+#define STBTT_strlen(x) strlen(x)
84+#define STBTT_memcpy memmove
85+#define STBTT_memset memset
86+typedef usize size_t;
87+#define NULL nil
88+#define STBTT_RASTERIZER_VERSION 1 /* that one is definitely FASTER on amd64 */
89+#include "pt_private.h"
90+
91+Sfont *
92+pt_font(uchar *data, float height)
93+{
94+ Sfont *f;
95+
96+ f = mallocz(sizeof(*f), 1);
97+ if(stbtt_InitFont(&f->fi, data, stbtt_GetFontOffsetForIndex(data, 0)) == 0)
98+ goto err;
99+
100+ f->c2g = stbtt_Code2Glyph(&f->fi);
101+ f->scale = stbtt_ScaleForPixelHeight(&f->fi, height);
102+ f->height = height;
103+ stbtt_GetFontVMetrics(&f->fi, &f->asc, &f->desc, &f->linegap);
104+ f->lineh = f->asc - f->desc + f->linegap;
105+
106+ stbtt_GetFontBoundingBox(&f->fi, &f->bb.min.x, &f->bb.min.y, &f->bb.max.x, &f->bb.max.y);
107+ f->bb.max.x = ceil(f->scale*(f->bb.max.x - f->bb.min.x));
108+ f->bb.max.y = ceil(f->scale*(f->bb.max.y - f->bb.min.y));
109+ f->bb.min.x = 0;
110+ f->bb.min.y = 0;
111+
112+ f->bb.max.x = (f->bb.max.x + 3) & ~3;
113+ f->bb.max.y = (f->bb.max.y + 3) & ~3;
114+
115+ if((f->g = allocmemimage(f->bb, GREY8)) == nil)
116+ goto err;
117+ if((f->white = allocmemimage(f->bb, GREY8)) == nil)
118+ goto err;
119+ memfillcolor(f->white, DWhite);
120+
121+ return f;
122+err:
123+ pt_freefont(f);
124+ return nil;
125+}
126+
127+void
128+pt_freefont(Sfont *f)
129+{
130+ if(f == nil)
131+ return;
132+ free(f->c2g);
133+ freememimage(f->g);
134+ freememimage(f->white);
135+ free(f);
136+}
137+
138+static u32int *
139+bsearch(u32int c, u32int *t, int n)
140+{
141+ u32int *p;
142+ int m;
143+
144+ while(n > 1){
145+ m = n/2;
146+ p = t + m;
147+ if(c >= p[0]) {
148+ t = p;
149+ n = n-m;
150+ } else
151+ n = m;
152+ }
153+ if(n && c >= t[0])
154+ return t;
155+ return 0;
156+}
157+
158+static int
159+code2glyph(Sfont *f, u32int c)
160+{
161+ u32int *r;
162+
163+ if((r = bsearch(c, f->c2g->code, f->c2g->num)) != nil)
164+ return f->c2g->glyph[r - f->c2g->code];
165+ return 0;
166+}
167+
168+Rectangle
169+pt_textrect(Sfont *f, char *s)
170+{
171+ int i, n;
172+ int glyph, prevglyph, adv, kern, leftb;
173+ int w, h, maxw;
174+ Rune r;
175+
176+ w = maxw = 0;
177+ h = f->lineh;
178+ prevglyph = 0;
179+ for(i = 0; s[i]; i += n){
180+ n = chartorune(&r, s+i);
181+ glyph = code2glyph(f, r);
182+ if(r != '\n' && glyph > 0){
183+ stbtt_GetGlyphHMetrics(&f->fi, glyph, &adv, &leftb);
184+ kern = prevglyph ? stbtt_GetGlyphKernAdvance(&f->fi, prevglyph, glyph) : 0;
185+ w += adv + kern;
186+ }else
187+ glyph = 0;
188+ prevglyph = glyph;
189+ maxw = MAX(maxw, w);
190+ if(r == '\n'){
191+ h += f->lineh;
192+ w = 0;
193+ }
194+ }
195+ w = ceil(f->scale*maxw);
196+ h = ceil(f->scale*(h+1));
197+
198+ return Rect(0, 0, w, h);
199+}
200+
201+Image *
202+pt_textdraw(Sfont *f, char *s, Rectangle rect, Sdopts *opts)
203+{
204+ int i, base, n, x0, y0, prefilter;
205+ int glyph, prevglyph, adv, leftb;
206+ float x, shift, subx, suby;
207+ Rune r;
208+ Rectangle o;
209+ Memimage *mi;
210+ Image *image;
211+ uchar *p;
212+
213+ if((mi = allocmemimage(rect, GREY8)) == nil)
214+ return nil;
215+ memfillcolor(mi, DWhite);
216+ prevglyph = 0;
217+ x = 0.0f;
218+ o = rect;
219+ base = 0;
220+ prefilter = opts != nil ? opts->prefilter : 0;
221+ if(prefilter > STBTT_MAX_OVERSAMPLE)
222+ prefilter = STBTT_MAX_OVERSAMPLE;
223+
224+ for(i = 0; s[i]; i += n){
225+ n = chartorune(&r, s+i);
226+ glyph = code2glyph(f, r);
227+
228+ if(prevglyph > 0 && glyph > 0 && r != '\n')
229+ x += stbtt_GetGlyphKernAdvance(&f->fi, prevglyph, glyph) * f->scale;
230+ shift = x - floor(x);
231+
232+ if(r != '\n' && glyph > 0){
233+ memfillcolor(f->g, DBlack);
234+
235+ if(prefilter > 0){
236+ stbtt_MakeGlyphBitmapSubpixelPrefilter(
237+ &f->fi,
238+ byteaddr(f->g, f->bb.min),
239+ Dx(f->bb), Dy(f->bb),
240+ bytesperline(f->bb, f->g->depth),
241+ f->scale, f->scale,
242+ shift, 0.0f,
243+ prefilter, prefilter,
244+ &subx, &suby,
245+ glyph
246+ );
247+ }else{
248+ stbtt_MakeGlyphBitmapSubpixel(
249+ &f->fi,
250+ byteaddr(f->g, f->bb.min),
251+ Dx(f->bb), Dy(f->bb),
252+ bytesperline(f->bb, f->g->depth),
253+ f->scale, f->scale,
254+ shift, 0.0f,
255+ glyph
256+ );
257+ }
258+
259+ stbtt_GetGlyphBitmapBoxSubpixel(
260+ &f->fi,
261+ glyph,
262+ f->scale, f->scale,
263+ shift, 0.0f,
264+ &x0, &y0, nil, nil
265+ );
266+ o.min.x = floor(x) + x0;
267+ o.min.y = base + f->asc*f->scale + y0;
268+ memimagedraw(mi, o, f->white, ZP, f->g, ZP, DoutS);
269+ stbtt_GetGlyphHMetrics(&f->fi, glyph, &adv, &leftb);
270+ x += adv * f->scale;
271+ }else
272+ glyph = 0;
273+ prevglyph = glyph;
274+ if(r == '\n'){
275+ x = x0 = 0;
276+ prevglyph = 0;
277+ base += ceil(f->scale * f->lineh);
278+ }
279+ }
280+
281+ n = 60 + Dx(rect)*Dy(rect);
282+ p = malloc(n);
283+ n = unloadmemimage(mi, rect, p, n);
284+ freememimage(mi);
285+
286+ image = allocimage(display, rect, GREY8, 0, DNofill);
287+ if(opts != nil && opts->gamma != 1.0){
288+ float igamma = 1.0/opts->gamma;
289+ for(i = 0; i < n; i++){
290+ if(p[i] < 255){
291+ float g = pow(p[i], igamma);
292+ p[i] = g < 256 ? g : 255;
293+ }
294+ }
295+ }
296+ if(opts != nil && opts->invert){
297+ for(i = 0; i < n; i++)
298+ p[i] = 255 - p[i];
299+ }
300+ loadimage(image, rect, p, n);
301+ free(p);
302+
303+ return image;
304+}
pt.h+20−0
@@ -0,0 +1,20 @@
1+typedef struct Sdopts Sdopts;
2+typedef struct Sfont Sfont;
3+#pragma incomplete Sfont
4+
5+struct Sdopts {
6+ int invert;
7+ int prefilter;
8+ float gamma;
9+};
10+
11+struct Sfontinfo {
12+ char *family;
13+ char *subfamily;
14+
15+};
16+
17+Sfont *pt_font(uchar *data, float height);
18+void pt_freefont(Sfont *f);
19+Rectangle pt_textrect(Sfont *f, char *s);
20+Image *pt_textdraw(Sfont *f, char *s, Rectangle rect, Sdopts *opts);
pt_private.h+18−0
@@ -0,0 +1,18 @@
1+#include "stb_truetype.h"
2+
3+struct Sfont {
4+ Memimage *g;
5+ Memimage *white;
6+
7+ stbtt_code2glyph *c2g;
8+
9+ Rectangle bb;
10+ float scale;
11+ float height;
12+ int asc;
13+ int desc;
14+ int linegap;
15+ int lineh;
16+
17+ stbtt_fontinfo fi;
18+};
test.c+22−343
@@ -5,115 +5,22 @@ · 4 unmodified lines
55 #include <memdraw.h>
66 #include <mouse.h>
77 #include <thread.h>
8−#define STB_TRUETYPE_IMPLEMENTATION
9−#define STBTT_ifloor(x) ((int)floor(x))
10−#define STBTT_iceil(x) ((int)ceil(x))
11−#define STBTT_sqrt(x) sqrt(x)
12−#define STBTT_pow(x,y) pow(x,y)
13−#define STBTT_fmod(x,y) fmod(x,y)
14−#define STBTT_cos(x) cos(x)
15−#define STBTT_acos(x) acos(x)
16−#define STBTT_fabs(x) fabs(x)
17−#define STBTT_malloc(x,u) ((void)(u),malloc(x))
18−#define STBTT_free(x,u) ((void)(u),free(x))
19−#define STBTT_assert(x) assert(x)
20−#define STBTT_strlen(x) strlen(x)
21−#define STBTT_memcpy memmove
22−#define STBTT_memset memset
23−typedef usize size_t;
24−#define NULL nil
25−#define STBTT_RASTERIZER_VERSION 1 /* that one is definitely FASTER on amd64 */
26−static int utf16to8(uchar *o, int osz, const uchar *s, int sz);
27−#include "stb_truetype.h"
8+#include "pt.h"
289
2910 #define MAX(a,b) ((a)>=(b)?(a):(b))
3011
31−typedef struct Sfont Sfont;
32−
33−struct Sfont {
34− Memimage *g;
35− Memimage *white;
36−
37− stbtt_code2glyph *c2g;
38−
39− Rectangle bb;
40− float scale;
41− float height;
42− int asc;
43− int desc;
44− int linegap;
45− int lineh;
46−
47− stbtt_fontinfo fi;
48−};
49−
50−static Sfont fo;
12+static Sfont *fo;
5113 static Image *image;
5214 static int invert, prefilter;
5315 static Point offset = {8, 8};
54−static float gamma = 1.0;
16+static Sdopts opts = {
17+ .invert = 0,
18+ .prefilter = 0,
19+ .gamma = 1.0,
20+};
5521 static char info[128];
5622 int mainstacksize = 32768;
5723
58−uvlong nanosec(void);
59−
60−#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
61−
62−static const uchar mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
63−
64−static int
65−utf16to8(uchar *o, int osz, const uchar *s, int sz)
66−{
67− int i, be, c, c2, wr, j;
68−
69− i = 0;
70− be = 1;
71− if(s[0] == 0xfe && s[1] == 0xff)
72− i += 2;
73− else if(s[0] == 0xff && s[1] == 0xfe){
74− be = 0;
75− i += 2;
76− }
77−
78− for(; i < sz-1 && osz > 1;){
79− c = rchr(&s[i]);
80− i += 2;
81− if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
82− c2 = rchr(&s[i]);
83− if(c2 >= 0xdc00 && c2 <= 0xdfff){
84− c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
85− i += 2;
86− }else
87− return -1;
88− }else if(c >= 0xdc00 && c <= 0xdfff)
89− return -1;
90−
91− if(c < 0x80)
92− wr = 1;
93− else if(c < 0x800)
94− wr = 2;
95− else if(c < 0x10000)
96− wr = 3;
97− else
98− wr = 4;
99−
100− osz -= wr;
101− if(osz < 1)
102− break;
103−
104− o += wr;
105− for(j = wr; j > 1; j--){
106− *(--o) = (c & 0xbf) | 0x80;
107− c >>= 6;
108− }
109− *(--o) = c | mark[wr];
110− o += wr;
111− }
112−
113− *o = 0;
114− return i;
115−}
116−
11724 static void
11825 redraw(void)
11926 {
@@ -168,230 +75,6 @@ end: · 48 unmodified lines
16875 return d;
16976 }
17077
171−int
172−initfont(Sfont *f, uchar *data, float height)
173−{
174− if(data != nil && stbtt_InitFont(&f->fi, data, stbtt_GetFontOffsetForIndex(data, 0)) == 0)
175− return -1;
176−
177− free(f->c2g);
178− f->c2g = stbtt_Code2Glyph(&f->fi);
179−
180− f->scale = stbtt_ScaleForPixelHeight(&f->fi, height);
181− f->height = height;
182− stbtt_GetFontVMetrics(&f->fi, &f->asc, &f->desc, &f->linegap);
183− f->lineh = f->asc - f->desc + f->linegap;
184−
185− stbtt_GetFontBoundingBox(&f->fi, &f->bb.min.x, &f->bb.min.y, &f->bb.max.x, &f->bb.max.y);
186− f->bb.max.x = ceil(f->scale*(f->bb.max.x - f->bb.min.x));
187− f->bb.max.y = ceil(f->scale*(f->bb.max.y - f->bb.min.y));
188− f->bb.min.x = 0;
189− f->bb.min.y = 0;
190−
191− f->bb.max.x = (f->bb.max.x + 3) & ~3;
192− f->bb.max.y = (f->bb.max.y + 3) & ~3;
193−
194− freememimage(f->g);
195− if((f->g = allocmemimage(f->bb, GREY8)) == nil)
196− return -1;
197−
198− freememimage(f->white);
199− if((f->white = allocmemimage(f->bb, GREY8)) == nil)
200− return -1;
201− memfillcolor(f->white, DWhite);
202−
203− return 0;
204−}
205−
206−static u32int *
207−bsearch(u32int c, u32int *t, int n)
208−{
209− u32int *p;
210− int m;
211−
212− while(n > 1){
213− m = n/2;
214− p = t + m;
215− if(c >= p[0]) {
216− t = p;
217− n = n-m;
218− } else
219− n = m;
220− }
221− if(n && c >= t[0])
222− return t;
223− return 0;
224−}
225−
226−int
227−code2glyph(Sfont *f, u32int c)
228−{
229− u32int *r;
230−
231− if((r = bsearch(c, f->c2g->code, f->c2g->num)) != nil)
232− return f->c2g->glyph[r - f->c2g->code];
233− return 0;
234−}
235−
236−Rectangle
237−textrect(Sfont *f, char *s)
238−{
239− int i, n;
240− int glyph, prevglyph, adv, kern, leftb;
241− int w, h, maxw;
242− Rune r;
243−
244− w = maxw = 0;
245− h = f->lineh;
246− prevglyph = 0;
247− for(i = 0; s[i]; i += n){
248− n = chartorune(&r, s+i);
249− glyph = code2glyph(f, r);
250− if(r != '\n' && glyph > 0){
251− stbtt_GetGlyphHMetrics(&f->fi, glyph, &adv, &leftb);
252− kern = prevglyph ? stbtt_GetGlyphKernAdvance(&f->fi, prevglyph, glyph) : 0;
253− w += adv + kern;
254− }else
255− glyph = 0;
256− prevglyph = glyph;
257− maxw = MAX(maxw, w);
258− if(r == '\n'){
259− h += f->lineh;
260− w = 0;
261− }
262− }
263− w = ceil(f->scale*maxw);
264− h = ceil(f->scale*(h+1));
265−
266− return Rect(0, 0, w, h);
267−}
268−
269−static void
270−prepare(Sfont *f, char *s)
271−{
272− int i, base, n, x0, y0;
273− int glyph, prevglyph, adv, leftb;
274− float x, shift, subx, suby;
275− Rune r;
276− Rectangle rect, o;
277− Memimage *mi;
278− uchar *p;
279− uvlong t[8][3];
280−
281− memset(t, 0, sizeof(t));
282−#define STATSTART(i) do{ \
283− t[i][0] = nanosec(); \
284−}while(0)
285−#define STATEND(i) do{ \
286− t[i][1] += nanosec()-t[i][0]; \
287− t[i][2]++; \
288−}while(0)
289−
290−STATSTART(0);
291−
292− rect = textrect(f, s);
293− if((mi = allocmemimage(rect, GREY8)) == nil)
294− sysfatal("%r");
295− memfillcolor(mi, DWhite);
296− prevglyph = 0;
297− x = 0.0f;
298− o = rect;
299− base = 0;
300−
301− for(i = 0; s[i]; i += n){
302−STATSTART(1);
303− n = chartorune(&r, s+i);
304− glyph = code2glyph(f, r);
305−
306− if(prevglyph > 0 && glyph > 0 && r != '\n')
307− x += stbtt_GetGlyphKernAdvance(&f->fi, prevglyph, glyph) * f->scale;
308− shift = x - floor(x);
309−
310− if(r != '\n' && glyph > 0){
311− memfillcolor(f->g, DBlack);
312−STATEND(1);
313−STATSTART(2);
314− if(prefilter)
315− stbtt_MakeGlyphBitmapSubpixelPrefilter(
316− &f->fi,
317− byteaddr(f->g, f->bb.min),
318− Dx(f->bb), Dy(f->bb),
319− bytesperline(f->bb, f->g->depth),
320− f->scale, f->scale,
321− shift, 0.0f,
322− prefilter, prefilter,
323− &subx, &suby,
324− glyph
325− );
326− else
327− stbtt_MakeGlyphBitmapSubpixel(
328− &f->fi,
329− byteaddr(f->g, f->bb.min),
330− Dx(f->bb), Dy(f->bb),
331− bytesperline(f->bb, f->g->depth),
332− f->scale, f->scale,
333− shift, 0.0f,
334− glyph
335− );
336−STATEND(2);
337−STATSTART(3);
338− stbtt_GetGlyphBitmapBoxSubpixel(
339− &f->fi,
340− glyph,
341− f->scale, f->scale,
342− shift, 0.0f,
343− &x0, &y0, nil, nil
344− );
345−STATEND(3);
346−STATSTART(4);
347− o.min.x = floor(x) + x0;
348− o.min.y = base + f->asc*f->scale + y0;
349− memimagedraw(mi, o, f->white, ZP, f->g, ZP, DoutS);
350− stbtt_GetGlyphHMetrics(&f->fi, glyph, &adv, &leftb);
351− x += adv * f->scale;
352−STATEND(4);
353− }else
354− glyph = 0;
355− prevglyph = glyph;
356− if(r == '\n'){
357− x = x0 = 0;
358− prevglyph = 0;
359− base += ceil(f->scale * f->lineh);
360− }
361− }
362−
363− n = 60 + Dx(rect)*Dy(rect);
364− p = malloc(n);
365− n = unloadmemimage(mi, rect, p, n);
366− freememimage(mi);
367−
368− lockdisplay(display);
369− freeimage(image);
370− image = allocimage(display, rect, GREY8, 0, DNofill);
371− if(gamma != 1.0){
372− for(i = 0; i < n; i++){
373− if(p[i] < 255){
374− float g = pow(p[i], 1.0/gamma);
375− p[i] = g < 256 ? g : 255;
376− }
377− }
378− }
379− if(invert){
380− for(i = 0; i < n; i++)
381− p[i] = 255 - p[i];
382− }
383− loadimage(image, rect, p, n);
384− unlockdisplay(display);
385− free(p);
386−
387−STATEND(0);
388−
389− s = info;
390− s += sprint(s, "%dpx prefilter=%d gamma=%.3g ", (int)f->height, prefilter, gamma);
391− for(i = 0; i < 4; i++)
392− s = seprint(s, info+sizeof(info), "%zd(%zd) ", (t[i][1]/t[i][2])/1000ULL, t[i][2]);
393−}
394−
39578 void
39679 threadmain(int argc, char **argv)
39780 {
@@ -410,6 +93,7 @@ threadmain(int argc, char **argv) · 12 unmodified lines
41093 int oldheight, height;
41194 Point oldxy, oldoffset;
41295 int oldb;
96+ Rectangle rect;
41397
41498 quotefmtinstall();
41599
@@ -439,13 +123,7 @@ threadmain(int argc, char **argv) · 23 unmodified lines
439123 oldheight = height;
440124 oldxy = ZP;
441125
442− if(initfont(&fo, data, height) != 0)
443− sysfatal("initfont");
444− prepare(&fo, s);
445− print("%s %s\n", fo.fi.family, fo.fi.subfamily);
446− print("max glyphs: %d\n", fo.fi.numGlyphs);
447− print("underlinePosition: %d\n", fo.fi.underlinePosition);
448− print("underlineThickness: %d\n", fo.fi.underlineThickness);
126+ goto changed;
449127
450128 for(;;){
451129 oldb = m.buttons;
@@ -486,37 +164,38 @@ threadmain(int argc, char **argv) · 34 unmodified lines
486164 height += 1;
487165 goto changed;
488166 case 'i':
489− invert = !invert;
167+ opts.invert = !opts.invert;
490168 goto changed;
491169 case Kleft:
492− prefilter--;
170+ opts.prefilter--;
493171 if(prefilter < 0)
494172 prefilter = 0;
495173 goto changed;
496174 case Kright:
497− prefilter++;
498− if(prefilter > STBTT_MAX_OVERSAMPLE)
499− prefilter = STBTT_MAX_OVERSAMPLE;
175+ opts.prefilter++;
500176 goto changed;
501177 case Kup:
502− gamma += 0.01;
178+ opts.gamma += 0.01;
503179 goto changed;
504180 case Kdown:
505− gamma -= 0.01;
506− if(gamma < 0.4)
507− gamma = 0.4;
181+ opts.gamma -= 0.01;
182+ if(opts.gamma < 0.4)
183+ opts.gamma = 0.4;
508184 goto changed;
509185 break;
510186 case '\n':
511− gamma = 1.0;
187+ opts.gamma = 1.0;
512188 goto changed;
513189 }
514190 }
515191 continue;
516192
517193 changed:
518− initfont(&fo, data, height);
519− prepare(&fo, s);
194+ pt_freefont(fo);
195+ fo = pt_font(data, height);
196+ rect = pt_textrect(fo, s);
197+ freeimage(image);
198+ image = pt_textdraw(fo, s, rect, &opts);
520199 }
521200
522201 end:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t