summaryrefslogtreecommitdiff
path: root/libinterp/freetype.c
diff options
context:
space:
mode:
Diffstat (limited to 'libinterp/freetype.c')
-rw-r--r--libinterp/freetype.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/libinterp/freetype.c b/libinterp/freetype.c
new file mode 100644
index 00000000..860b119d
--- /dev/null
+++ b/libinterp/freetype.c
@@ -0,0 +1,231 @@
+#include <lib9.h>
+#include <kernel.h>
+#include "interp.h"
+#include "isa.h"
+#include "runt.h"
+#include "raise.h"
+#include "freetypemod.h"
+#include "freetype.h"
+
+
+typedef struct Face Face;
+struct Face {
+ Freetype_Face freetypeface; /* limbo part */
+ FTface ftface; /* private parts */
+};
+
+Type* TMatrix;
+Type* TVector;
+Type* TFace;
+Type* TGlyph;
+
+static uchar Matrixmap[] = Freetype_Matrix_map;
+static uchar Vectormap[] = Freetype_Vector_map;
+static uchar Facemap[] = Freetype_Face_map;
+static uchar Glyphmap[] = Freetype_Glyph_map;
+
+static void freeface(Heap*, int);
+static Face* ckface(Freetype_Face*);
+
+void
+freetypemodinit(void)
+{
+ builtinmod("$Freetype", Freetypemodtab, Freetypemodlen);
+ TMatrix = dtype(freeheap, sizeof(Freetype_Matrix), Matrixmap, sizeof(Matrixmap));
+ TVector = dtype(freeheap, sizeof(Freetype_Vector), Vectormap, sizeof(Vectormap));
+ TFace = dtype(freeface, sizeof(Face), Facemap, sizeof(Facemap));
+ TGlyph = dtype(freeheap, sizeof(Freetype_Glyph), Glyphmap, sizeof(Glyphmap));
+}
+
+void
+Face_haschar(void *fp)
+{
+ F_Face_haschar *f = fp;
+ Face *face;
+
+ *f->ret = 0;
+ face = ckface(f->face);
+ release();
+ *f->ret = fthaschar(face->ftface, f->c);
+ acquire();
+}
+
+void
+Face_loadglyph(void *fp)
+{
+ F_Face_loadglyph *f = fp;
+ Heap *h;
+ Face *face;
+ Freetype_Glyph *g;
+ FTglyph ftg;
+ int n, i, s1bpr, s2bpr;
+ char *err;
+
+ face = ckface(f->face);
+
+ destroy(*f->ret);
+ *f->ret = H;
+
+ release();
+ err = ftloadglyph(face->ftface, f->c, &ftg);
+ acquire();
+ if (err != nil) {
+ kwerrstr(err);
+ return;
+ }
+
+ h = heap(TGlyph);
+ if (h == H) {
+ kwerrstr(exNomem);
+ return;
+ }
+ g = H2D(Freetype_Glyph*, h);
+ n = ftg.width*ftg.height;
+ h = heaparray(&Tbyte, n);
+ if (h == H) {
+ destroy(g);
+ kwerrstr(exNomem);
+ return;
+ }
+ g->bitmap = H2D(Array*, h);
+ g->top = ftg.top;
+ g->left = ftg.left;
+ g->height = ftg.height;
+ g->width = ftg.width;
+ g->advance.x = ftg.advx;
+ g->advance.y = ftg.advy;
+
+ s1bpr = ftg.width;
+ s2bpr = ftg.bpr;
+ for (i = 0; i < ftg.height; i++)
+ memcpy(g->bitmap->data+(i*s1bpr), ftg.bitmap+(i*s2bpr), s1bpr);
+ *f->ret = g;
+}
+
+void
+Freetype_newface(void *fp)
+{
+ F_Freetype_newface *f = fp;
+ Heap *h;
+ Face *face;
+ Freetype_Face *limboface;
+ FTfaceinfo finfo;
+ char *path;
+ char *err;
+
+ destroy(*f->ret);
+ *f->ret = H;
+
+ h = heapz(TFace);
+ if (h == H) {
+ kwerrstr(exNomem);
+ return;
+ }
+
+ face = H2D(Face*, h);
+ limboface = (Freetype_Face*)face;
+ *f->ret = limboface;
+ path = strdup(string2c(f->path)); /* string2c() can call error() */
+ release();
+ err = ftnewface(path, f->index, &face->ftface, &finfo);
+ acquire();
+ free(path);
+ if (err != nil) {
+ *f->ret = H;
+ destroy(face);
+ kwerrstr(err);
+ return;
+ }
+ limboface->nfaces = finfo.nfaces;
+ limboface->index = finfo.index;
+ limboface->style = finfo.style;
+ limboface->height = finfo.height;
+ limboface->ascent = finfo.ascent;
+ limboface->familyname = c2string(finfo.familyname, strlen(finfo.familyname));
+ limboface->stylename = c2string(finfo.stylename, strlen(finfo.stylename));
+ *f->ret = limboface;
+}
+
+void
+Freetype_newmemface(void *fp)
+{
+ F_Freetype_newmemface *f = fp;
+
+ destroy(*f->ret);
+ *f->ret = H;
+
+ kwerrstr("not implemented");
+}
+
+void
+Face_setcharsize(void *fp)
+{
+ F_Face_setcharsize *f = fp;
+ Face *face;
+ Freetype_Face *limboface;
+ FTfaceinfo finfo;
+ char *err;
+
+ face = ckface(f->face);
+ limboface = (Freetype_Face*)face;
+ release();
+ err = ftsetcharsize(face->ftface, f->pts, f->hdpi, f->vdpi, &finfo);
+ acquire();
+ if (err == nil) {
+ limboface->height = finfo.height;
+ limboface->ascent = finfo.ascent;
+ }
+ retstr(err, f->ret);
+}
+
+void
+Face_settransform(void *fp)
+{
+ F_Face_settransform *f = fp;
+ FTmatrix *m = nil;
+ FTvector *v = nil;
+ Face *face;
+
+ face = ckface(f->face);
+
+ /*
+ * ftsettransform() has no error return
+ * we have one for consistency - but always nil for now
+ */
+ destroy(*f->ret);
+ *f->ret = H;
+
+ if (f->m != H)
+ m = (FTmatrix*)(f->m);
+ if (f->v != H)
+ v = (FTvector*)(f->v);
+ release();
+ ftsettransform(face->ftface, m, v);
+ acquire();
+}
+
+static void
+freeface(Heap *h, int swept)
+{
+ Face *face = H2D(Face*, h);
+
+ if (!swept) {
+ destroy(face->freetypeface.familyname);
+ destroy(face->freetypeface.stylename);
+ }
+ release();
+ ftdoneface(face->ftface);
+ acquire();
+ memset(&face->ftface, 0, sizeof(face->ftface));
+}
+
+static Face*
+ckface(Freetype_Face *face)
+{
+ if (face == nil || face == H)
+ error("nil Face");
+ if (D2H(face)->t != TFace)
+ error(exType);
+ return (Face*)face;
+}
+