xref: /inferno-os/libinterp/freetype.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1 #include <lib9.h>
2 #include <kernel.h>
3 #include "interp.h"
4 #include "isa.h"
5 #include "runt.h"
6 #include "raise.h"
7 #include "freetypemod.h"
8 #include "freetype.h"
9 
10 
11 typedef struct Face Face;
12 struct Face {
13 	Freetype_Face	freetypeface;		/* limbo part */
14 	FTface		ftface;			/* private parts */
15 };
16 
17 Type*	TMatrix;
18 Type*	TVector;
19 Type*	TFace;
20 Type*	TGlyph;
21 
22 static uchar	Matrixmap[] = Freetype_Matrix_map;
23 static uchar	Vectormap[] = Freetype_Vector_map;
24 static uchar	Facemap[] = Freetype_Face_map;
25 static uchar	Glyphmap[] = Freetype_Glyph_map;
26 
27 static void		freeface(Heap*, int);
28 static Face*	ckface(Freetype_Face*);
29 
30 void
31 freetypemodinit(void)
32 {
33 	builtinmod("$Freetype", Freetypemodtab, Freetypemodlen);
34 	TMatrix = dtype(freeheap, sizeof(Freetype_Matrix), Matrixmap, sizeof(Matrixmap));
35 	TVector = dtype(freeheap, sizeof(Freetype_Vector), Vectormap, sizeof(Vectormap));
36 	TFace = dtype(freeface, sizeof(Face), Facemap, sizeof(Facemap));
37 	TGlyph = dtype(freeheap, sizeof(Freetype_Glyph), Glyphmap, sizeof(Glyphmap));
38 }
39 
40 void
41 Face_haschar(void *fp)
42 {
43 	F_Face_haschar *f = fp;
44 	Face *face;
45 
46 	*f->ret = 0;
47 	face = ckface(f->face);
48 	release();
49 	*f->ret = fthaschar(face->ftface, f->c);
50 	acquire();
51 }
52 
53 void
54 Face_loadglyph(void *fp)
55 {
56 	F_Face_loadglyph *f = fp;
57 	Heap *h;
58 	Face *face;
59 	Freetype_Glyph *g;
60 	FTglyph ftg;
61 	int n, i, s1bpr, s2bpr;
62 	char *err;
63 
64 	face = ckface(f->face);
65 
66 	destroy(*f->ret);
67 	*f->ret = H;
68 
69 	release();
70 	err = ftloadglyph(face->ftface, f->c, &ftg);
71 	acquire();
72 	if (err != nil) {
73 		kwerrstr(err);
74 		return;
75 	}
76 
77 	h = heap(TGlyph);
78 	if (h == H) {
79 		kwerrstr(exNomem);
80 		return;
81 	}
82 	g = H2D(Freetype_Glyph*, h);
83 	n = ftg.width*ftg.height;
84 	h = heaparray(&Tbyte, n);
85 	if (h == H) {
86 		destroy(g);
87 		kwerrstr(exNomem);
88 		return;
89 	}
90 	g->bitmap = H2D(Array*, h);
91 	g->top = ftg.top;
92 	g->left = ftg.left;
93 	g->height = ftg.height;
94 	g->width = ftg.width;
95 	g->advance.x = ftg.advx;
96 	g->advance.y = ftg.advy;
97 
98 	s1bpr = ftg.width;
99 	s2bpr = ftg.bpr;
100 	for (i = 0; i < ftg.height; i++)
101 		memcpy(g->bitmap->data+(i*s1bpr), ftg.bitmap+(i*s2bpr), s1bpr);
102 	*f->ret = g;
103 }
104 
105 void
106 Freetype_newface(void *fp)
107 {
108 	F_Freetype_newface *f = fp;
109 	Heap *h;
110 	Face *face;
111 	Freetype_Face *limboface;
112 	FTfaceinfo finfo;
113 	char *path;
114 	char *err;
115 
116 	destroy(*f->ret);
117 	*f->ret = H;
118 
119 	h = heapz(TFace);
120 	if (h == H) {
121 		kwerrstr(exNomem);
122 		return;
123 	}
124 
125 	face = H2D(Face*, h);
126 	limboface = (Freetype_Face*)face;
127 	*f->ret = limboface;
128 	path = strdup(string2c(f->path));	/* string2c() can call error() */
129 	release();
130 	err = ftnewface(path, f->index, &face->ftface, &finfo);
131 	acquire();
132 	free(path);
133 	if (err != nil) {
134 		*f->ret = H;
135 		destroy(face);
136 		kwerrstr(err);
137 		return;
138 	}
139 	limboface->nfaces = finfo.nfaces;
140 	limboface->index = finfo.index;
141 	limboface->style = finfo.style;
142 	limboface->height = finfo.height;
143 	limboface->ascent = finfo.ascent;
144 	limboface->familyname = c2string(finfo.familyname, strlen(finfo.familyname));
145 	limboface->stylename = c2string(finfo.stylename, strlen(finfo.stylename));
146 	*f->ret = limboface;
147 }
148 
149 void
150 Freetype_newmemface(void *fp)
151 {
152 	F_Freetype_newmemface *f = fp;
153 
154 	destroy(*f->ret);
155 	*f->ret = H;
156 
157 	kwerrstr("not implemented");
158 }
159 
160 void
161 Face_setcharsize(void *fp)
162 {
163 	F_Face_setcharsize *f = fp;
164 	Face *face;
165 	Freetype_Face *limboface;
166 	FTfaceinfo finfo;
167 	char *err;
168 
169 	face = ckface(f->face);
170 	limboface = (Freetype_Face*)face;
171 	release();
172 	err = ftsetcharsize(face->ftface, f->pts, f->hdpi, f->vdpi, &finfo);
173 	acquire();
174 	if (err == nil) {
175 		limboface->height = finfo.height;
176 		limboface->ascent = finfo.ascent;
177 	}
178 	retstr(err, f->ret);
179 }
180 
181 void
182 Face_settransform(void *fp)
183 {
184 	F_Face_settransform *f = fp;
185 	FTmatrix *m = nil;
186 	FTvector *v = nil;
187 	Face *face;
188 
189 	face = ckface(f->face);
190 
191 	/*
192 	 * ftsettransform() has no error return
193 	 * we have one for consistency - but always nil for now
194 	 */
195 	destroy(*f->ret);
196 	*f->ret = H;
197 
198 	if (f->m != H)
199 		m = (FTmatrix*)(f->m);
200 	if (f->v != H)
201 		v = (FTvector*)(f->v);
202 	release();
203 	ftsettransform(face->ftface, m, v);
204 	acquire();
205 }
206 
207 static void
208 freeface(Heap *h, int swept)
209 {
210 	Face *face = H2D(Face*, h);
211 
212 	if (!swept) {
213 		destroy(face->freetypeface.familyname);
214 		destroy(face->freetypeface.stylename);
215 	}
216 	release();
217 	ftdoneface(face->ftface);
218 	acquire();
219 	memset(&face->ftface, 0, sizeof(face->ftface));
220 }
221 
222 static Face*
223 ckface(Freetype_Face *face)
224 {
225 	if (face == nil || face == H)
226 		error("nil Face");
227 	if (D2H(face)->t != TFace)
228 		error(exType);
229 	return (Face*)face;
230 }
231 
232