Project

General

Profile

Statistics
| Revision:

root / proj / libs / graph / src / font.c @ 316

History | View | Annotate | Download (6.71 KB)

1 182 up20180642
#include <lcom/lcf.h>
2
3
#include "font.h"
4
5 183 up20180642
#include "xpm_utils.h"
6
#include "graph.h"
7
#include "utils.h"
8
#include "errors.h"
9 188 up20180642
#include <assert.h>
10 183 up20180642
11 314 up20180642
/// GLYPH
12 182 up20180642
struct glyph{
13
    uint16_t w, h;
14
    uint8_t *map;
15
};
16 183 up20180642
typedef struct glyph glyph_t;
17
static glyph_t* (glyph_ctor)(const char **xpm){
18
    if(xpm == NULL) return NULL;
19 182 up20180642
    glyph_t *ret = malloc(sizeof(glyph_t));
20
    if(ret == NULL) return NULL;
21
    enum xpm_image_type type = XPM_8_8_8_8;
22
    xpm_image_t img;
23 213 up20180642
    ret->map = NULL;
24
    uint8_t *map = xpm_load((xpm_map_t)xpm, type, &img);
25
    if(map == NULL){
26 182 up20180642
        free(ret);
27
        return NULL;
28
    }
29
    ret->w = img.width;
30
    ret->h = img.height;
31 213 up20180642
    ret->map = malloc(ret->w*ret->h*sizeof(uint8_t));
32
    if(ret->map == NULL){
33
        free(ret);
34
        return NULL;
35
    }
36
    for(unsigned i = 0; i < ret->w*ret->h; ++i){
37
        ret->map[i] = map[4*i+3];
38
    }
39 182 up20180642
    return ret;
40
}
41 183 up20180642
static void (glyph_dtor)(glyph_t *p){
42 182 up20180642
    if(p == NULL) return;
43
    free(p->map);
44
    free(p);
45
}
46 183 up20180642
static int (glyph_draw_to_alpha_buffer)(const glyph_t *p, int16_t x, int16_t y, uint8_t *alp_buf, uint16_t W, uint16_t H){
47
    if(p == NULL) return NULL_PTR;
48
    for(int16_t h = 0; h < p->h; ++h){
49
        for(int16_t w = 0; w < p->w; ++w){
50 213 up20180642
            uint8_t a = *(p->map + w + h*p->w);
51 208 up20180642
            int16_t x_ = x+w, y_ = y-p->h+h;
52
            unsigned pos = x_ +y_*W;
53
            alp_buf[pos] = a;
54 183 up20180642
        }
55
    }
56
    return SUCCESS;
57
}
58
59 314 up20180642
/// FONT
60 183 up20180642
struct font{
61
    size_t nchars;
62
    glyph_t **glyphs;
63
};
64
font_t* (font_ctor)(const char *s){
65
    font_t *ret = malloc(sizeof(font_t));
66
    if(ret == NULL) return NULL;
67
    ret->nchars = 128;
68
    ret->glyphs = malloc(ret->nchars*sizeof(glyph_t*));
69
    if(ret->glyphs == NULL){
70
        free(ret->glyphs);
71
        free(ret);
72
        return NULL;
73
    }
74 192 up20180642
    int good = false;
75 183 up20180642
    char filepath[1024];
76
    for(size_t i = 0; i < ret->nchars; ++i){
77
        sprintf(filepath, "%s/ascii%03d.xpm2", s, i);
78
        char **xpm = xpm_load_xpm2(filepath);
79
        ret->glyphs[i] = glyph_ctor((const char**)xpm);
80 192 up20180642
        if(ret->glyphs[i] != NULL) good = true;
81 183 up20180642
    }
82 192 up20180642
    if(good) return ret;
83
    else{
84
        //font_dtor(ret);
85
        return NULL;
86
    }
87 183 up20180642
}
88 313 up20180642
int (font_dtor)(font_t *p){
89
    if(p == NULL) return SUCCESS;
90 183 up20180642
    for(size_t i = 0; i < p->nchars; ++i)
91
        glyph_dtor(p->glyphs[i]);
92
    free(p->glyphs);
93
    free(p);
94 313 up20180642
    return SUCCESS;
95 183 up20180642
}
96
97 314 up20180642
static font_t *consolas     = NULL;
98
static font_t *default_font = NULL;
99 313 up20180642
100
int (font_init)(void){
101
    consolas = font_ctor("/home/lcom/labs/proj/media/font/Consolas/xpm2");
102
    if(consolas == NULL) return NULL_PTR;
103
    default_font = consolas;
104
    return SUCCESS;
105
}
106 314 up20180642
const font_t* font_get_default(void){ return default_font; }
107
const font_t* font_get_consolas(void){ return consolas; }
108 313 up20180642
int (font_free)(void){
109
    int r;
110
    if((r = font_dtor(consolas))) return r;
111
    consolas = NULL;
112
    default_font = NULL;
113
    return SUCCESS;
114
}
115
116 314 up20180642
/// TEXT
117 183 up20180642
struct text{
118
    const font_t *fnt;
119
    char *txt;
120
    int16_t x, y;
121
    int size;
122
    uint32_t color;
123 314 up20180642
    text_valign valign;
124
    text_halign halign;
125 183 up20180642
};
126
text_t* (text_ctor)(const font_t *fnt, const char *txt){
127
    if(fnt == NULL) return NULL;
128
    text_t *ret = malloc(sizeof(text_t));
129
    if(ret == NULL) return NULL;
130
    ret->fnt = fnt;
131
    ret->txt = NULL;
132 314 up20180642
    text_set_string(ret, txt);
133 183 up20180642
    ret->x = 0;
134
    ret->y = 0;
135 188 up20180642
    ret->size = 25;
136 253 up20180642
    ret->color = GRAPH_BLACK;
137 188 up20180642
    ret->valign = text_valign_top;
138
    ret->halign = text_halign_left;
139 183 up20180642
    return ret;
140
}
141
void (text_dtor)(text_t *p){
142
    if(p == NULL) return;
143
    free(p->txt);
144
    free(p);
145
}
146 314 up20180642
void (text_set_string) (text_t *p, const char *txt){
147 183 up20180642
    size_t sz = strlen(txt);
148
    p->txt = realloc(p->txt, (sz+1)*sizeof(char));
149
    if(p->txt == NULL) return;
150
    strcpy(p->txt, txt);
151
}
152 250 up20180655
char* (text_get_string)(const text_t *p){return p->txt; }
153 314 up20180642
void (text_set_pos)   (text_t *p, int16_t x, int16_t y){ p->x = x; p->y = y; }
154
void (text_set_size)  (text_t *p, unsigned size       ){ p->size = size    ; }
155
void (text_set_color) (text_t *p, uint32_t color      ){ p->color = color  ; }
156
void (text_set_valign)(text_t *p, text_valign valign  ){ p->valign = valign; }
157
void (text_set_halign)(text_t *p, text_halign halign  ){ p->halign = halign; }
158 297 up20180642
int16_t (text_get_x)  (const text_t *p){ return p->x; }
159
int16_t (text_get_y)  (const text_t *p){ return p->y; }
160 183 up20180642
161 188 up20180642
int (text_draw)(const text_t *p){
162
    if(p == NULL) return NULL_PTR;
163
    int ret = SUCCESS;
164
    // Get buffer with rescaled text
165
    uint8_t *alp_new_buf = NULL;
166
    uint16_t newH, newW;{
167
        const size_t len = strlen(p->txt);
168
        uint16_t W = 0, H = 0; {
169
            for(size_t i = 0; i < len; ++i){
170
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
171
                if(g != NULL){ W += g->w; H = max(H, g->h); }
172
            }
173
        }
174
        uint8_t *alp_buf = malloc(W*H);
175
        if(alp_buf == NULL) return ALLOC_ERROR;{
176
            int16_t y = H;
177
            int16_t x = 0;
178
            for(size_t i = 0; i < len; ++i){
179
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
180
                if(g != NULL){
181
                    if((ret = glyph_draw_to_alpha_buffer(g, x, y, alp_buf, W, H))) return ret;
182
                    x += g->w;
183
                }
184
            }
185
        }
186 183 up20180642
187 188 up20180642
        double factor = (double)p->size/(double)H;
188
189
        newH = H*factor;
190
        newW = W*factor;
191
        alp_new_buf = malloc(newW*newH);
192
        if(alp_new_buf == NULL) return ALLOC_ERROR;
193
194
        for(size_t newy = 0; newy < newH; ++newy){
195 298 up20180642
            size_t y = newy/factor;
196 188 up20180642
            for(size_t newx = 0; newx < newW; ++newx){
197 298 up20180642
                size_t x = newx/factor;
198 188 up20180642
                *(alp_new_buf+newx+newy*newW) = *(alp_buf+x+y*W);
199 183 up20180642
            }
200
        }
201 188 up20180642
        free(alp_buf);
202
    }
203
    // Get initial value of x
204
    int16_t initx;{
205
        switch(p->halign){
206
            case text_halign_left  : initx = p->x         ; break;
207
            case text_halign_center: initx = p->x - newW/2; break;
208
            case text_halign_right : initx = p->x - newW  ; break;
209
            default: return LOGIC_ERROR;
210 183 up20180642
        }
211
    }
212 188 up20180642
    // Get initial value of y
213
    int16_t inity;{
214
        switch(p->valign){
215
            case text_valign_top   : inity = p->y         ; break;
216
            case text_valign_center: inity = p->y - newH/2; break;
217
            case text_valign_bottom: inity = p->y - newH  ; break;
218
            default: return LOGIC_ERROR;
219 183 up20180642
        }
220
    }
221 188 up20180642
    // Draw text
222 307 up20180642
    for(int16_t x, y, newy = 0; newy < newH; ++newy){
223
        y = inity+newy;
224 188 up20180642
        for(int16_t newx = 0; newx < newW; ++newx){
225 307 up20180642
            x = initx+newx;
226
            if(!(0 <= x && x < graph_get_XRes() &&
227
                 0 <= y && y < graph_get_YRes())) continue;
228 188 up20180642
            uint8_t a = *(alp_new_buf+newx+newy*newW);
229 307 up20180642
            if(a < ALPHA_THRESHOLD) graph_set_pixel(x,y,p->color);
230 188 up20180642
        }
231
    }
232
    free(alp_new_buf);
233
    return SUCCESS;
234 183 up20180642
}