+int copy_bitmap(const FT_Bitmap *bmp, Image *image)
+{
+ unsigned x, y;
+ unsigned char *src;
+ unsigned char *dst;
+
+ image->w = bmp->width;
+ image->h = bmp->rows;
+ if(!image->w || !image->h)
+ {
+ image->data = NULL;
+ return 0;
+ }
+
+ image->data = (unsigned char *)malloc(image->w*image->h);
+ if(!image->data)
+ {
+ fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
+ return -1;
+ }
+
+ if(bmp->pitch<0)
+ src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
+ else
+ src = bmp->buffer;
+ dst = image->data;
+
+ for(y=0; y<bmp->rows; ++y)
+ {
+ if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
+ {
+ for(x=0; x<bmp->width; ++x)
+ dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
+ }
+ else
+ {
+ for(x=0; x<bmp->width; ++x)
+ dst[x] = src[x];
+ }
+
+ src += bmp->pitch;
+ dst += image->w;
+ }
+
+ return 0;
+}
+
+void propagate_distance(unsigned short *pixel, int offset)
+{
+ unsigned short *neighbor = pixel+offset;
+ if((*neighbor^*pixel)&0x8000)
+ *neighbor = (*neighbor&0x8000)+1;
+ else if((*neighbor&0x7FFF)>(*pixel&0x7FFF))
+ *neighbor = *pixel+2;
+}
+
+int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
+{
+ unsigned x, y;
+ Image base_image;
+ unsigned short *distance_map;
+ unsigned map_w;
+ unsigned map_h;
+ unsigned offset;
+
+ if(!bmp->width || !bmp->rows)
+ {
+ image->w = 0;
+ image->h = 0;
+ image->data = NULL;
+ return 0;
+ }
+
+ if(copy_bitmap(bmp, &base_image))
+ return -1;
+
+ map_w = base_image.w+2*margin*scale+scale-1;
+ map_w -= map_w%scale;
+ map_h = base_image.h+2*margin*scale+scale-1;
+ map_h -= map_h%scale;
+ distance_map = (unsigned short *)malloc(map_w*map_h*sizeof(unsigned short));
+ if(!distance_map)
+ {
+ fprintf(stderr, "Cannot allocate %d bytes of memory for distance map\n", map_w*map_h);
+ free(base_image.data);
+ return -1;
+ }
+
+ image->w = map_w/scale;
+ image->h = map_h/scale;
+ image->data = (unsigned char *)malloc(image->w*image->h);
+ if(!image->data)
+ {
+ fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
+ free(base_image.data);
+ free(distance_map);
+ return -1;
+ }
+
+ for(x=0; x<map_w*map_h; ++x)
+ distance_map[x] = 0x7FFF;
+
+ offset = margin*scale*(map_w+1);
+ for(y=0; y<base_image.h; ++y) for(x=0; x<base_image.w; ++x)
+ distance_map[offset+x+y*map_w] |= (base_image.data[x+y*base_image.w]&0x80)<<8;
+
+ for(y=0; y<map_h; ++y)
+ {
+ for(x=0; x+1<map_w; ++x)
+ propagate_distance(distance_map+x+y*map_w, 1);
+ for(x=map_w-1; x>0; --x)
+ propagate_distance(distance_map+x+y*map_w, -1);
+ }
+
+ for(x=0; x<map_w; ++x)
+ {
+ for(y=0; y+1<map_h; ++y)
+ propagate_distance(distance_map+x+y*map_w, map_w);
+ for(y=map_h-1; y>0; --y)
+ propagate_distance(distance_map+x+y*map_w, -map_w);
+ }
+
+ offset = scale/2*(map_w+1);
+ for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
+ {
+ unsigned short pixel = distance_map[offset+(x+y*map_w)*scale];
+ unsigned short dist = (pixel&0x7FFF)*0x7F/(margin*scale*2+1);
+ if(dist>0x7F)
+ dist = 0x7F;
+ if(pixel&0x8000)
+ image->data[x+y*image->w] = 0x80+dist;
+ else
+ image->data[x+y*image->w] = 0x7F-dist;
+ }
+
+ free(distance_map);
+ free(base_image.data);
+
+ return 0;
+}
+
+int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot)