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