Blame


1 9c611279 2012-10-21 rsc #include <u.h>
2 9c611279 2012-10-21 rsc
3 9c611279 2012-10-21 rsc #include <fontconfig/fontconfig.h>
4 9c611279 2012-10-21 rsc #include <ft2build.h>
5 9c611279 2012-10-21 rsc #include FT_FREETYPE_H
6 9c611279 2012-10-21 rsc
7 9c611279 2012-10-21 rsc #include <libc.h>
8 9c611279 2012-10-21 rsc #include <draw.h>
9 9c611279 2012-10-21 rsc #include <memdraw.h>
10 9c611279 2012-10-21 rsc #include "a.h"
11 9c611279 2012-10-21 rsc
12 9c611279 2012-10-21 rsc static FcConfig *fc;
13 9c611279 2012-10-21 rsc static FT_Library lib;
14 9c611279 2012-10-21 rsc static int dpi = 96;
15 9c611279 2012-10-21 rsc
16 9c611279 2012-10-21 rsc void
17 9c611279 2012-10-21 rsc loadfonts(void)
18 9c611279 2012-10-21 rsc {
19 9c611279 2012-10-21 rsc int i;
20 9c611279 2012-10-21 rsc FT_Error e;
21 9c611279 2012-10-21 rsc FcFontSet *sysfonts;
22 9c611279 2012-10-21 rsc
23 9c611279 2012-10-21 rsc if(!FcInit() || (fc=FcInitLoadConfigAndFonts()) == NULL) {
24 9c611279 2012-10-21 rsc fprint(2, "fontconfig initialization failed\n");
25 9c611279 2012-10-21 rsc exits("fontconfig failed");
26 9c611279 2012-10-21 rsc }
27 9c611279 2012-10-21 rsc
28 9c611279 2012-10-21 rsc e = FT_Init_FreeType(&lib);
29 9c611279 2012-10-21 rsc if(e) {
30 9c611279 2012-10-21 rsc fprint(2, "freetype initialization failed: %d\n", e);
31 9c611279 2012-10-21 rsc exits("freetype failed");
32 9c611279 2012-10-21 rsc }
33 9c611279 2012-10-21 rsc
34 9c611279 2012-10-21 rsc sysfonts = FcConfigGetFonts(fc, FcSetSystem);
35 9c611279 2012-10-21 rsc
36 9c611279 2012-10-21 rsc xfont = emalloc9p(sysfonts->nfont*sizeof xfont[0]);
37 9c611279 2012-10-21 rsc memset(xfont, 0, sysfonts->nfont*sizeof xfont[0]);
38 9c611279 2012-10-21 rsc for(i=0; i<sysfonts->nfont; i++) {
39 9c611279 2012-10-21 rsc FcChar8 *fullname, *fontfile;
40 9c611279 2012-10-21 rsc int index;
41 9c611279 2012-10-21 rsc FcPattern *pat = sysfonts->fonts[i];
42 9c611279 2012-10-21 rsc
43 9c611279 2012-10-21 rsc if(FcPatternGetString(pat, FC_FULLNAME, 0, &fullname) != FcResultMatch ||
44 9c611279 2012-10-21 rsc FcPatternGetString(pat, FC_FILE, 0, &fontfile) != FcResultMatch ||
45 9c611279 2012-10-21 rsc FcPatternGetInteger(pat, FC_INDEX, 0, &index) != FcResultMatch)
46 9c611279 2012-10-21 rsc continue;
47 9c611279 2012-10-21 rsc
48 9c611279 2012-10-21 rsc xfont[nxfont].name = strdup((char*)fullname);
49 9c611279 2012-10-21 rsc xfont[nxfont].fontfile = strdup((char*)fontfile);
50 9c611279 2012-10-21 rsc xfont[nxfont].index = index;
51 9c611279 2012-10-21 rsc nxfont++;
52 9c611279 2012-10-21 rsc }
53 9c611279 2012-10-21 rsc
54 9c611279 2012-10-21 rsc FcFontSetDestroy(sysfonts);
55 9c611279 2012-10-21 rsc }
56 9c611279 2012-10-21 rsc
57 9c611279 2012-10-21 rsc void
58 9c611279 2012-10-21 rsc load(XFont *f)
59 9c611279 2012-10-21 rsc {
60 9c611279 2012-10-21 rsc FT_Face face;
61 9c611279 2012-10-21 rsc FT_Error e;
62 9c611279 2012-10-21 rsc FT_ULong charcode;
63 9c611279 2012-10-21 rsc FT_UInt glyph_index;
64 9c611279 2012-10-21 rsc
65 9c611279 2012-10-21 rsc if(f->loaded)
66 9c611279 2012-10-21 rsc return;
67 9c611279 2012-10-21 rsc
68 9c611279 2012-10-21 rsc e = FT_New_Face(lib, f->fontfile, f->index, &face);
69 9c611279 2012-10-21 rsc
70 9c611279 2012-10-21 rsc if(e){
71 9c611279 2012-10-21 rsc fprint(2, "load failed for %s (%s) index:%d\n", f->name, f->fontfile, f->index);
72 9c611279 2012-10-21 rsc return;
73 9c611279 2012-10-21 rsc }
74 9c611279 2012-10-21 rsc
75 9c611279 2012-10-21 rsc if(!FT_IS_SCALABLE(face)) {
76 9c611279 2012-10-21 rsc fprint(2, "%s is a non scalable font, skipping\n", f->name);
77 9c611279 2012-10-21 rsc FT_Done_Face(face);
78 9c611279 2012-10-21 rsc f->loaded = 1;
79 9c611279 2012-10-21 rsc return;
80 9c611279 2012-10-21 rsc }
81 9c611279 2012-10-21 rsc
82 9c611279 2012-10-21 rsc f->unit = face->units_per_EM;
83 9c611279 2012-10-21 rsc f->height = (int)((face->ascender - face->descender) * 1.2);
84 9c611279 2012-10-21 rsc f->originy = face->descender; // bbox.yMin (or descender) is negative, becase the baseline is y-coord 0
85 9c611279 2012-10-21 rsc
86 9c611279 2012-10-21 rsc for(charcode=FT_Get_First_Char(face, &glyph_index); glyph_index != 0;
87 9c611279 2012-10-21 rsc charcode=FT_Get_Next_Char(face, charcode, &glyph_index)) {
88 9c611279 2012-10-21 rsc
89 9c611279 2012-10-21 rsc int idx = charcode>>8;
90 9c611279 2012-10-21 rsc
91 9c611279 2012-10-21 rsc if(charcode > 0xffff)
92 9c611279 2012-10-21 rsc break;
93 9c611279 2012-10-21 rsc
94 9c611279 2012-10-21 rsc if(!f->range[idx]) {
95 9c611279 2012-10-21 rsc f->range[idx] = 1;
96 9c611279 2012-10-21 rsc f->nrange++;
97 9c611279 2012-10-21 rsc }
98 9c611279 2012-10-21 rsc }
99 9c611279 2012-10-21 rsc
100 9c611279 2012-10-21 rsc FT_Done_Face(face);
101 9c611279 2012-10-21 rsc f->loaded = 1;
102 9c611279 2012-10-21 rsc }
103 9c611279 2012-10-21 rsc
104 9c611279 2012-10-21 rsc Memsubfont*
105 9c611279 2012-10-21 rsc mksubfont(char *name, int lo, int hi, int size, int antialias)
106 9c611279 2012-10-21 rsc {
107 9c611279 2012-10-21 rsc XFont *xf, *xfp, *xfe;
108 9c611279 2012-10-21 rsc FT_Face face;
109 9c611279 2012-10-21 rsc FT_Error e;
110 9c611279 2012-10-21 rsc Memimage *m, *mc, *m1;
111 9c611279 2012-10-21 rsc double pixel_size;
112 9c611279 2012-10-21 rsc int x, y, y0;
113 9c611279 2012-10-21 rsc int i;
114 9c611279 2012-10-21 rsc Fontchar *fc, *fc0;
115 9c611279 2012-10-21 rsc Memsubfont *sf;
116 63002b3e 2014-03-03 0intro //Point rect_points[4];
117 9c611279 2012-10-21 rsc
118 9c611279 2012-10-21 rsc xf = nil;
119 9c611279 2012-10-21 rsc for(xfp=xfont, xfe=xfont+nxfont; xfp != xfe; xfp++) {
120 9c611279 2012-10-21 rsc if(strcmp(xfp->name, name) == 0) {
121 9c611279 2012-10-21 rsc xf = xfp;
122 9c611279 2012-10-21 rsc break;
123 9c611279 2012-10-21 rsc }
124 9c611279 2012-10-21 rsc }
125 9c611279 2012-10-21 rsc
126 9c611279 2012-10-21 rsc if(!xf)
127 9c611279 2012-10-21 rsc return nil;
128 9c611279 2012-10-21 rsc
129 9c611279 2012-10-21 rsc e = FT_New_Face(lib, xf->fontfile, xf->index, &face);
130 9c611279 2012-10-21 rsc
131 9c611279 2012-10-21 rsc if(e){
132 9c611279 2012-10-21 rsc fprint(2, "load failed for %s (%s) index:%d\n", xf->name, xf->fontfile, xf->index);
133 9c611279 2012-10-21 rsc return nil;
134 9c611279 2012-10-21 rsc }
135 9c611279 2012-10-21 rsc
136 9c611279 2012-10-21 rsc e = FT_Set_Char_Size(face, 0, size<<6, dpi, dpi);
137 9c611279 2012-10-21 rsc if(e){
138 9c611279 2012-10-21 rsc fprint(2, "FT_Set_Char_Size failed\n");
139 9c611279 2012-10-21 rsc FT_Done_Face(face);
140 9c611279 2012-10-21 rsc return nil;
141 9c611279 2012-10-21 rsc }
142 9c611279 2012-10-21 rsc
143 9c611279 2012-10-21 rsc pixel_size = (dpi*size)/72.0;
144 9c611279 2012-10-21 rsc x = (int)((face->max_advance_width) * pixel_size/xf->unit + 0.99999999);
145 9c611279 2012-10-21 rsc y = (int)((face->ascender - face->descender) * pixel_size/xf->unit + 0.99999999);
146 9c611279 2012-10-21 rsc y0 = (int)(-face->descender * pixel_size/xf->unit + 0.99999999);
147 9c611279 2012-10-21 rsc
148 9c611279 2012-10-21 rsc m = allocmemimage(Rect(0, 0, x*(hi+1-lo), y), antialias ? GREY8 : GREY1);
149 9c611279 2012-10-21 rsc if(m == nil) {
150 9c611279 2012-10-21 rsc FT_Done_Face(face);
151 9c611279 2012-10-21 rsc return nil;
152 9c611279 2012-10-21 rsc }
153 9c611279 2012-10-21 rsc mc = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1);
154 9c611279 2012-10-21 rsc if(mc == nil) {
155 9c611279 2012-10-21 rsc freememimage(m);
156 9c611279 2012-10-21 rsc FT_Done_Face(face);
157 9c611279 2012-10-21 rsc return nil;
158 9c611279 2012-10-21 rsc }
159 9c611279 2012-10-21 rsc memfillcolor(m, DBlack);
160 9c611279 2012-10-21 rsc memfillcolor(mc, DBlack);
161 9c611279 2012-10-21 rsc fc = malloc((hi+2 - lo) * sizeof fc[0]);
162 9c611279 2012-10-21 rsc sf = malloc(sizeof *sf);
163 9c611279 2012-10-21 rsc if(fc == nil || sf == nil) {
164 9c611279 2012-10-21 rsc freememimage(m);
165 9c611279 2012-10-21 rsc freememimage(mc);
166 9c611279 2012-10-21 rsc free(fc);
167 9c611279 2012-10-21 rsc free(sf);
168 9c611279 2012-10-21 rsc FT_Done_Face(face);
169 9c611279 2012-10-21 rsc return nil;
170 9c611279 2012-10-21 rsc }
171 9c611279 2012-10-21 rsc fc0 = fc;
172 9c611279 2012-10-21 rsc
173 9c611279 2012-10-21 rsc //rect_points[0] = mc->r.min;
174 9c611279 2012-10-21 rsc //rect_points[1] = Pt(mc->r.max.x, mc->r.min.y);
175 9c611279 2012-10-21 rsc //rect_points[2] = mc->r.max;
176 9c611279 2012-10-21 rsc //rect_points[3] = Pt(mc->r.min.x, mc->r.max.y);
177 9c611279 2012-10-21 rsc
178 9c611279 2012-10-21 rsc x = 0;
179 9c611279 2012-10-21 rsc for(i=lo; i<=hi; i++, fc++) {
180 9c611279 2012-10-21 rsc int r;
181 9c611279 2012-10-21 rsc int advance;
182 9c611279 2012-10-21 rsc
183 9c611279 2012-10-21 rsc memfillcolor(mc, DBlack);
184 9c611279 2012-10-21 rsc
185 9c611279 2012-10-21 rsc e = FT_Load_Char(face, i, FT_LOAD_RENDER|(antialias ? 0:FT_LOAD_TARGET_MONO));
186 9c611279 2012-10-21 rsc if(e){
187 9c611279 2012-10-21 rsc fprint(2, "FT_Load_Char failed for %d\n", i);
188 9c611279 2012-10-21 rsc //mempoly(mc, rect_points, 4, Endsquare, Endsquare, 0, memopaque, ZP, S);
189 9c611279 2012-10-21 rsc memimageline(mc, m->r.min, Pt(m->r.max.x, m->r.min.y), Endsquare, Endsquare, 0, memopaque, ZP, S);
190 9c611279 2012-10-21 rsc memimageline(mc, m->r.min, Pt(m->r.min.x, m->r.max.y), Endsquare, Endsquare, 0, memopaque, ZP, S);
191 9c611279 2012-10-21 rsc memimageline(mc, Pt(m->r.max.x, m->r.min.y), m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
192 9c611279 2012-10-21 rsc memimageline(mc, Pt(m->r.min.x, m->r.max.y), m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
193 9c611279 2012-10-21 rsc memimageline(mc, m->r.min, m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
194 9c611279 2012-10-21 rsc advance = Dx(m->r);
195 9c611279 2012-10-21 rsc
196 9c611279 2012-10-21 rsc memimagedraw(m, Rect(x, 0, x + advance, y), mc, ZP, memopaque, ZP, S);
197 9c611279 2012-10-21 rsc } else {
198 9c611279 2012-10-21 rsc FT_Bitmap *bitmap = &face->glyph->bitmap;
199 9c611279 2012-10-21 rsc uchar *base = byteaddr(mc, mc->r.min);
200 9c611279 2012-10-21 rsc advance = (face->glyph->advance.x+32) >> 6;
201 9c611279 2012-10-21 rsc
202 9c611279 2012-10-21 rsc for(r=0; r < bitmap->rows; r++)
203 9c611279 2012-10-21 rsc memmove(base + r*mc->width*sizeof(u32int), bitmap->buffer + r*bitmap->pitch, bitmap->pitch);
204 9c611279 2012-10-21 rsc
205 9c611279 2012-10-21 rsc memimagedraw(m, Rect(x, 0, x + advance, y), mc,
206 9c611279 2012-10-21 rsc Pt(-face->glyph->bitmap_left, -(y - y0 - face->glyph->bitmap_top)),
207 9c611279 2012-10-21 rsc memopaque, ZP, S);
208 9c611279 2012-10-21 rsc }
209 9c611279 2012-10-21 rsc
210 9c611279 2012-10-21 rsc fc->x = x;
211 9c611279 2012-10-21 rsc fc->top = 0;
212 9c611279 2012-10-21 rsc fc->bottom = y;
213 9c611279 2012-10-21 rsc fc->left = 0;
214 9c611279 2012-10-21 rsc fc->width = advance;
215 9c611279 2012-10-21 rsc x += advance;
216 9c611279 2012-10-21 rsc
217 9c611279 2012-10-21 rsc #ifdef DEBUG_FT_BITMAP
218 9c611279 2012-10-21 rsc for(r=0; r < bitmap->rows; r++) {
219 9c611279 2012-10-21 rsc int c;
220 9c611279 2012-10-21 rsc uchar *span = bitmap->buffer+(r*bitmap->pitch);
221 9c611279 2012-10-21 rsc for(c = 0; c < bitmap->width; c++) {
222 9c611279 2012-10-21 rsc fprint(1, "%02x", span[c]);
223 9c611279 2012-10-21 rsc }
224 9c611279 2012-10-21 rsc fprint(1,"\n");
225 9c611279 2012-10-21 rsc }
226 9c611279 2012-10-21 rsc #endif
227 9c611279 2012-10-21 rsc
228 9c611279 2012-10-21 rsc #ifdef DEBUG_9_BITMAP
229 9c611279 2012-10-21 rsc for(r=0; r < mc->r.max.y; r++) {
230 9c611279 2012-10-21 rsc int c;
231 9c611279 2012-10-21 rsc uchar *span = base+(r*mc->width*sizeof(u32int));
232 9c611279 2012-10-21 rsc for(c = 0; c < Dx(mc->r); c++) {
233 9c611279 2012-10-21 rsc fprint(1, "%02x", span[c]);
234 9c611279 2012-10-21 rsc }
235 9c611279 2012-10-21 rsc fprint(1,"\n");
236 9c611279 2012-10-21 rsc }
237 9c611279 2012-10-21 rsc #endif
238 9c611279 2012-10-21 rsc }
239 9c611279 2012-10-21 rsc fc->x = x;
240 9c611279 2012-10-21 rsc
241 9c611279 2012-10-21 rsc // round up to 32-bit boundary
242 9c611279 2012-10-21 rsc // so that in-memory data is same
243 9c611279 2012-10-21 rsc // layout as in-file data.
244 9c611279 2012-10-21 rsc if(antialias)
245 9c611279 2012-10-21 rsc x += -x & 3;
246 9c611279 2012-10-21 rsc else
247 9c611279 2012-10-21 rsc x += -x & 31;
248 9c611279 2012-10-21 rsc m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1);
249 9c611279 2012-10-21 rsc memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S);
250 9c611279 2012-10-21 rsc freememimage(m);
251 9c611279 2012-10-21 rsc
252 9c611279 2012-10-21 rsc sf->name = nil;
253 9c611279 2012-10-21 rsc sf->n = hi+1 - lo;
254 9c611279 2012-10-21 rsc sf->height = Dy(m1->r);
255 9c611279 2012-10-21 rsc sf->ascent = Dy(m1->r) - y0;
256 9c611279 2012-10-21 rsc sf->info = fc0;
257 9c611279 2012-10-21 rsc sf->bits = m1;
258 9c611279 2012-10-21 rsc
259 9c611279 2012-10-21 rsc FT_Done_Face(face);
260 9c611279 2012-10-21 rsc return sf;
261 9c611279 2012-10-21 rsc }