Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (6.57 KB)

1
#include <lcom/lcf.h>
2

    
3
#include "font.h"
4

    
5
#include "xpm_utils.h"
6
#include "graph.h"
7
#include "utils.h"
8
#include "errors.h"
9
#include <assert.h>
10

    
11
struct glyph{
12
    uint16_t w, h;
13
    uint8_t *map;
14
};
15
typedef struct glyph glyph_t;
16
static glyph_t* (glyph_ctor)(const char **xpm){
17
    if(xpm == NULL) return NULL;
18
    glyph_t *ret = malloc(sizeof(glyph_t));
19
    if(ret == NULL) return NULL;
20
    enum xpm_image_type type = XPM_8_8_8_8;
21
    xpm_image_t img;
22
    ret->map = NULL;
23
    uint8_t *map = xpm_load((xpm_map_t)xpm, type, &img);
24
    if(map == NULL){
25
        free(ret);
26
        return NULL;
27
    }
28
    ret->w = img.width;
29
    ret->h = img.height;
30
    ret->map = malloc(ret->w*ret->h*sizeof(uint8_t));
31
    if(ret->map == NULL){
32
        free(ret);
33
        return NULL;
34
    }
35
    for(unsigned i = 0; i < ret->w*ret->h; ++i){
36
        ret->map[i] = map[4*i+3];
37
    }
38
    return ret;
39
}
40
static void (glyph_dtor)(glyph_t *p){
41
    if(p == NULL) return;
42
    free(p->map);
43
    free(p);
44
}
45
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){
46
    if(p == NULL) return NULL_PTR;
47
    for(int16_t h = 0; h < p->h; ++h){
48
        for(int16_t w = 0; w < p->w; ++w){
49
            uint8_t a = *(p->map + w + h*p->w);
50
            int16_t x_ = x+w, y_ = y-p->h+h;
51
            unsigned pos = x_ +y_*W;
52
            alp_buf[pos] = a;
53
        }
54
    }
55
    return SUCCESS;
56
}
57

    
58
struct font{
59
    size_t nchars;
60
    glyph_t **glyphs;
61
};
62

    
63
font_t* (font_ctor)(const char *s){
64
    font_t *ret = malloc(sizeof(font_t));
65
    if(ret == NULL) return NULL;
66
    ret->nchars = 128;
67
    ret->glyphs = malloc(ret->nchars*sizeof(glyph_t*));
68
    if(ret->glyphs == NULL){
69
        free(ret->glyphs);
70
        free(ret);
71
        return NULL;
72
    }
73
    int good = false;
74
    char filepath[1024];
75
    for(size_t i = 0; i < ret->nchars; ++i){
76
        sprintf(filepath, "%s/ascii%03d.xpm2", s, i);
77
        char **xpm = xpm_load_xpm2(filepath);
78
        ret->glyphs[i] = glyph_ctor((const char**)xpm);
79
        if(ret->glyphs[i] != NULL) good = true;
80
    }
81
    if(good) return ret;
82
    else{
83
        //font_dtor(ret);
84
        return NULL;
85
    }
86
}
87
int (font_dtor)(font_t *p){
88
    if(p == NULL) return SUCCESS;
89
    for(size_t i = 0; i < p->nchars; ++i)
90
        glyph_dtor(p->glyphs[i]);
91
    free(p->glyphs);
92
    free(p);
93
    return SUCCESS;
94
}
95

    
96
font_t *consolas = NULL;
97
font_t *default_font = NULL;
98

    
99
int (font_init)(void){
100
    consolas = font_ctor("/home/lcom/labs/proj/media/font/Consolas/xpm2");
101
    if(consolas == NULL) return NULL_PTR;
102
    default_font = consolas;
103
    return SUCCESS;
104
}
105
int (font_free)(void){
106
    int r;
107
    if((r = font_dtor(consolas))) return r;
108
    consolas = NULL;
109
    default_font = NULL;
110
    return SUCCESS;
111
}
112

    
113
struct text{
114
    const font_t *fnt;
115
    char *txt;
116
    int16_t x, y;
117
    int size;
118
    uint32_t color;
119
    enum text_valign valign;
120
    enum text_halign halign;
121
};
122
text_t* (text_ctor)(const font_t *fnt, const char *txt){
123
    if(fnt == NULL) return NULL;
124
    text_t *ret = malloc(sizeof(text_t));
125
    if(ret == NULL) return NULL;
126
    ret->fnt = fnt;
127
    ret->txt = NULL;
128
    text_set_text(ret, txt);
129
    ret->x = 0;
130
    ret->y = 0;
131
    ret->size = 25;
132
    ret->color = GRAPH_BLACK;
133
    ret->valign = text_valign_top;
134
    ret->halign = text_halign_left;
135
    return ret;
136
}
137
void (text_dtor)(text_t *p){
138
    if(p == NULL) return;
139
    free(p->txt);
140
    free(p);
141
}
142
void (text_set_text) (text_t *p, const char *txt){
143
    size_t sz = strlen(txt);
144
    p->txt = realloc(p->txt, (sz+1)*sizeof(char));
145
    if(p->txt == NULL) return;
146
    strcpy(p->txt, txt);
147
}
148
char* (text_get_string)(const text_t *p){return p->txt; }
149
void (text_set_pos)   (text_t *p, int16_t x, int16_t y   ){ p->x = x; p->y = y; }
150
void (text_set_size)  (text_t *p, unsigned size          ){ p->size = size    ; }
151
void (text_set_color) (text_t *p, uint32_t color         ){ p->color = color  ; }
152
void (text_set_valign)(text_t *p, enum text_valign valign){ p->valign = valign; }
153
void (text_set_halign)(text_t *p, enum text_halign halign){ p->halign = halign; }
154
int16_t (text_get_x)  (const text_t *p){ return p->x; }
155
int16_t (text_get_y)  (const text_t *p){ return p->y; }
156

    
157
int (text_draw)(const text_t *p){
158
    if(p == NULL) return NULL_PTR;
159
    int ret = SUCCESS;
160
    // Get buffer with rescaled text
161
    uint8_t *alp_new_buf = NULL;
162
    uint16_t newH, newW;{
163
        const size_t len = strlen(p->txt);
164
        uint16_t W = 0, H = 0; {
165
            for(size_t i = 0; i < len; ++i){
166
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
167
                if(g != NULL){ W += g->w; H = max(H, g->h); }
168
            }
169
        }
170
        uint8_t *alp_buf = malloc(W*H);
171
        if(alp_buf == NULL) return ALLOC_ERROR;{
172
            int16_t y = H;
173
            int16_t x = 0;
174
            for(size_t i = 0; i < len; ++i){
175
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
176
                if(g != NULL){
177
                    if((ret = glyph_draw_to_alpha_buffer(g, x, y, alp_buf, W, H))) return ret;
178
                    x += g->w;
179
                }
180
            }
181
        }
182

    
183
        double factor = (double)p->size/(double)H;
184

    
185
        newH = H*factor;
186
        newW = W*factor;
187
        alp_new_buf = malloc(newW*newH);
188
        if(alp_new_buf == NULL) return ALLOC_ERROR;
189

    
190
        for(size_t newy = 0; newy < newH; ++newy){
191
            size_t y = newy/factor;
192
            for(size_t newx = 0; newx < newW; ++newx){
193
                size_t x = newx/factor;
194
                *(alp_new_buf+newx+newy*newW) = *(alp_buf+x+y*W);
195
            }
196
        }
197
        free(alp_buf);
198
    }
199
    // Get initial value of x
200
    int16_t initx;{
201
        switch(p->halign){
202
            case text_halign_left  : initx = p->x         ; break;
203
            case text_halign_center: initx = p->x - newW/2; break;
204
            case text_halign_right : initx = p->x - newW  ; break;
205
            default: return LOGIC_ERROR;
206
        }
207
    }
208
    // Get initial value of y
209
    int16_t inity;{
210
        switch(p->valign){
211
            case text_valign_top   : inity = p->y         ; break;
212
            case text_valign_center: inity = p->y - newH/2; break;
213
            case text_valign_bottom: inity = p->y - newH  ; break;
214
            default: return LOGIC_ERROR;
215
        }
216
    }
217
    // Draw text
218
    for(int16_t x, y, newy = 0; newy < newH; ++newy){
219
        y = inity+newy;
220
        for(int16_t newx = 0; newx < newW; ++newx){
221
            x = initx+newx;
222
            if(!(0 <= x && x < graph_get_XRes() &&
223
                 0 <= y && y < graph_get_YRes())) continue;
224
            uint8_t a = *(alp_new_buf+newx+newy*newW);
225
            if(a < ALPHA_THRESHOLD) graph_set_pixel(x,y,p->color);
226
        }
227
    }
228
    free(alp_new_buf);
229
    return SUCCESS;
230
}