font: don't segfault if font is wider than specified
[fbpad.git] / font.c
blob1be95864e5aeda2bdb1221ad0c86a80acfe5448f
1 #include <ft2build.h>
2 #include FT_FREETYPE_H
3 #include FT_BITMAP_H
4 #include "util.h"
6 #define FONTFACE "/usr/lib/X11/fonts/TTF/DejaVuSansMono.ttf"
7 #define FONTSIZE 10
8 #define DPI 192
9 #define MAXDOTS (1 << 10)
11 static FT_Library library;
12 static FT_Face face;
13 static int rows, cols;
15 void font_init(void)
17 FT_Init_FreeType(&library);
18 FT_New_Face(library, FONTFACE, 0, &face);
19 FT_Set_Char_Size(face, 0, FONTSIZE << 6, DPI, DPI);
20 rows = face->size->metrics.height >> 6;
21 cols = face->size->metrics.max_advance >> 6;
24 unsigned char *font_bitmap(int c, int bold)
26 static unsigned char bits[MAXDOTS];
27 int sr, sc, er, ec;
28 int i;
29 if (FT_Load_Char(face, c, FT_LOAD_RENDER))
30 return NULL;
31 if (bold) {
32 int FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot);
33 FT_GlyphSlot_Own_Bitmap(face->glyph);
34 FT_Bitmap_Embolden(library, &face->glyph->bitmap, 32, 32);
36 sr = rows + (face->size->metrics.descender >> 6) -
37 (face->glyph->metrics.horiBearingY >> 6);
38 sc = face->glyph->metrics.horiBearingX >> 6;
39 er = MIN(rows, sr + face->glyph->bitmap.rows);
40 ec = MIN(cols, sc + face->glyph->bitmap.width);
41 memset(bits, 0, sr * cols);
42 for (i = sr; i < er; i++) {
43 unsigned char *rowaddr = face->glyph->bitmap.buffer +
44 (i - sr) * face->glyph->bitmap.pitch;
45 memset(&bits[i * cols], 0, sc);
46 memcpy(&bits[i * cols + sc], rowaddr, ec - sc);
47 memset(&bits[i * cols + ec], 0, cols - ec);
49 memset(&bits[er * cols], 0, (rows - er) * cols);
50 return bits;
53 void font_free(void)
57 int font_rows(void)
59 return rows;
62 int font_cols(void)
64 return cols;