URI: 
       tx11.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tx11.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 }