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