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