added memory allocator
[winnie] / src / text.cc
1 #include <ft2build.h>
2 #include <freetype/freetype.h>
3
4 #include "gfx.h"
5 #include "shalloc.h"
6 #include "text.h"
7
8 #define DPI 72
9 #define FONT_PATH "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf"
10 #define FONT_SIZE 16
11
12 static int draw_glyph(Pixmap *pixmap, int x, int y, char c);
13
14 struct Text {
15         FT_Library ft_lib;
16         FT_Face ft_face;
17         int text_x, text_y;
18         int text_color[3];
19 };
20
21 static Text *text;
22
23 bool init_text()
24 {
25         if(!(text = (Text*)sh_malloc(sizeof *text))) {
26                 return false;
27         }
28
29         if(FT_Init_FreeType(&text->ft_lib)) {
30                 fprintf(stderr, "Failed to initialize the FreeType library!\n");
31                 return false;
32         }
33
34         if(FT_New_Face(text->ft_lib, FONT_PATH, 0, &text->ft_face)) {
35                 fprintf(stderr, "Failed to load font: %s\n", FONT_PATH);
36                 return false;
37         }
38
39         if(FT_Set_Char_Size(text->ft_face, 0, FONT_SIZE * 64, DPI, DPI)) {
40                 fprintf(stderr, "Failed to set font size\n");
41                 return false;
42         }
43
44         set_text_color(255, 255, 255);
45
46         return true;
47 }
48
49 void destroy_text()
50 {
51         sh_free(text);
52 }
53
54 void draw_text(const char *txt, Pixmap *pixmap)
55 {
56         if(!pixmap) {
57                 pixmap = get_framebuffer_pixmap();
58         }
59
60         while(*txt != 0) {
61                 text->text_x += draw_glyph(pixmap, text->text_x, text->text_y, *txt);
62                 txt++;
63         }
64 }
65
66 void set_text_position(int x, int y)
67 {
68         text->text_x = x;
69         text->text_y = y;
70
71 }
72
73 void set_text_color(int r, int g, int b)
74 {
75         text->text_color[0] = r;
76         text->text_color[1] = g;
77         text->text_color[2] = b;
78 }
79
80 static int draw_glyph(Pixmap *pixmap, int x, int y, char c)
81 {
82         if(FT_Load_Char(text->ft_face, c, FT_LOAD_RENDER)) {
83                 return 0;
84         }
85
86         x += text->ft_face->glyph->bitmap_left;
87         y -= text->ft_face->glyph->bitmap_top;
88
89         FT_Bitmap *ft_bmp = &text->ft_face->glyph->bitmap;
90         unsigned char *bmp_ptr = ft_bmp->buffer;
91         unsigned char *pxm_ptr = pixmap->get_image() + (pixmap->get_width() * y + x) * 4;
92
93         Rect clipping_rect = get_clipping_rect();
94
95         for(int i=0; i<ft_bmp->rows; i++) {
96                 int dest_y = i + y;
97                 if(dest_y >= clipping_rect.y + clipping_rect.height) {
98                         break;
99                 }
100
101                 if(dest_y >= clipping_rect.y) {
102                         for(int j=0; j<ft_bmp->width; j++) {
103                                 int dest_x = j + x;
104
105                                 if(dest_x >= clipping_rect.x + clipping_rect.width) {
106                                         break;
107                                 }
108
109                                 if(bmp_ptr[j] && dest_x >= clipping_rect.x) {
110                                         int a = (int)bmp_ptr[j];
111                                         pxm_ptr[4 * j] = (a * text->text_color[0] + pxm_ptr[4 * j] * (255 - a)) / 255;
112                                         pxm_ptr[4 * j + 1] = (a * text->text_color[1] + pxm_ptr[4 * j + 1] * (255 - a)) / 255;
113                                         pxm_ptr[4 * j + 2] = (a * text->text_color[2] + pxm_ptr[4 * j + 2] * (255 - a)) / 255;
114                                 }
115                         }
116                 }
117
118                 pxm_ptr += 4 * pixmap->get_width();
119                 bmp_ptr += ft_bmp->pitch;
120         }
121
122         return text->ft_face->glyph->advance.x >> 6;
123 }