Project

General

Profile

Statistics
| Revision:

root / proj / src / font.c @ 190

History | View | Annotate | Download (5.91 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 = xpm_load((xpm_map_t)xpm, type, &img);
23
    if(ret->map == NULL){
24
        free(ret);
25
        return NULL;
26
    }
27
    ret->w = img.width;
28
    ret->h = img.height;
29
    return ret;
30
}
31
static void (glyph_dtor)(glyph_t *p){
32
    if(p == NULL) return;
33
    free(p->map);
34
    free(p);
35
}
36
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){
37
    if(p == NULL) return NULL_PTR;
38
    int r;
39
    for(int16_t h = 0; h < p->h; ++h){
40
        for(int16_t w = 0; w < p->w; ++w){
41
            uint32_t c = *((uint32_t*)p->map + w + h*p->w);
42
            uint8_t a = GET_ALP(c);
43
            //c = c & 0xFF000000;
44
            //if(c != 0) printf("%d %d 0x%X\n", w, h, c);
45
            //else       printf("%d %d <========================\n");
46

    
47
            r = graph_set_pixel_alpha_buffer(x+w, y-p->h+h, a, alp_buf, W, H);
48

    
49

    
50
            //r = graph_set_pixel_alpha(x+w, y-p->h+h, GET_COLOR(c), GET_ALP(c));
51

    
52
            //printf("%d %d 0x%X\n", x, y, *(buf+(x+y*p->w)*sizeof(uint32_t)));
53
            if(r != SUCCESS && r != OUT_OF_RANGE) return r;
54
        }
55
    }
56
    return SUCCESS;
57
}
58

    
59
struct font{
60
    size_t nchars;
61
    glyph_t **glyphs;
62
};
63
#include "sprite.h"
64
#include "rectangle.h"
65
font_t* (font_ctor)(const char *s){
66
    font_t *ret = malloc(sizeof(font_t));
67
    if(ret == NULL) return NULL;
68
    ret->nchars = 128;
69
    ret->glyphs = malloc(ret->nchars*sizeof(glyph_t*));
70
    if(ret->glyphs == NULL){
71
        free(ret->glyphs);
72
        free(ret);
73
        return NULL;
74
    }
75
    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
    }
81
    return ret;
82
}
83
void (font_dtor)(font_t *p){
84
    if(p == NULL) return;
85
    for(size_t i = 0; i < p->nchars; ++i)
86
        glyph_dtor(p->glyphs[i]);
87
    free(p->glyphs);
88
    free(p);
89
}
90

    
91
struct text{
92
    const font_t *fnt;
93
    char *txt;
94
    int16_t x, y;
95
    int size;
96
    uint32_t color;
97
    enum text_valign valign;
98
    enum text_halign halign;
99
};
100
text_t* (text_ctor)(const font_t *fnt, const char *txt){
101
    if(fnt == NULL) return NULL;
102
    text_t *ret = malloc(sizeof(text_t));
103
    if(ret == NULL) return NULL;
104
    ret->fnt = fnt;
105
    ret->txt = NULL;
106
    text_set_text(ret, txt);
107
    ret->x = 0;
108
    ret->y = 0;
109
    ret->size = 25;
110
    ret->color = BLACK;
111
    ret->valign = text_valign_top;
112
    ret->halign = text_halign_left;
113
    return ret;
114
}
115
void (text_dtor)(text_t *p){
116
    if(p == NULL) return;
117
    free(p->txt);
118
    free(p);
119
}
120
void (text_set_text) (text_t *p, const char *txt){
121
    size_t sz = strlen(txt);
122
    p->txt = realloc(p->txt, (sz+1)*sizeof(char));
123
    if(p->txt == NULL) return;
124
    strcpy(p->txt, txt);
125
}
126
void (text_set_pos)   (text_t *p, int16_t x, int16_t y   ){ p->x = x; p->y = y; }
127
void (text_set_size)  (text_t *p, unsigned size          ){ p->size = size    ; }
128
void (text_set_color) (text_t *p, uint32_t color         ){ p->color = color  ; }
129
void (text_set_valign)(text_t *p, enum text_valign valign){ p->valign = valign; }
130
void (text_set_halign)(text_t *p, enum text_halign halign){ p->halign = halign; }
131

    
132
int (text_draw)(const text_t *p){
133
    if(p == NULL) return NULL_PTR;
134
    int ret = SUCCESS;
135
    // Get buffer with rescaled text
136
    uint8_t *alp_new_buf = NULL;
137
    uint16_t newH, newW;{
138
        const size_t len = strlen(p->txt);
139
        uint16_t W = 0, H = 0; {
140
            for(size_t i = 0; i < len; ++i){
141
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
142
                if(g != NULL){ W += g->w; H = max(H, g->h); }
143
            }
144
        }
145
        uint8_t *alp_buf = malloc(W*H);
146
        if(alp_buf == NULL) return ALLOC_ERROR;{
147
            int16_t y = H;
148
            int16_t x = 0;
149
            for(size_t i = 0; i < len; ++i){
150
                const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
151
                if(g != NULL){
152
                    if((ret = glyph_draw_to_alpha_buffer(g, x, y, alp_buf, W, H))) return ret;
153
                    x += g->w;
154
                }
155
            }
156
        }
157

    
158
        double factor = (double)p->size/(double)H;
159

    
160
        newH = H*factor;
161
        newW = W*factor;
162
        alp_new_buf = malloc(newW*newH);
163
        if(alp_new_buf == NULL) return ALLOC_ERROR;
164

    
165
        for(size_t newy = 0; newy < newH; ++newy){
166
            size_t y = newy/factor;
167
            for(size_t newx = 0; newx < newW; ++newx){
168
                size_t x = newx/factor;
169
                *(alp_new_buf+newx+newy*newW) = *(alp_buf+x+y*W);
170
            }
171
        }
172
        free(alp_buf);
173

    
174

    
175
    }
176
    // Get initial value of x
177
    int16_t initx;{
178
        switch(p->halign){
179
            case text_halign_left  : initx = p->x         ; break;
180
            case text_halign_center: initx = p->x - newW/2; break;
181
            case text_halign_right : initx = p->x - newW  ; break;
182
            default: return LOGIC_ERROR;
183
        }
184
    }
185
    // Get initial value of y
186
    int16_t inity;{
187
        switch(p->valign){
188
            case text_valign_top   : inity = p->y         ; break;
189
            case text_valign_center: inity = p->y - newH/2; break;
190
            case text_valign_bottom: inity = p->y - newH  ; break;
191
            default: return LOGIC_ERROR;
192
        }
193
    }
194
    // Draw text
195
    for(int16_t newy = 0; newy < newH; ++newy){
196
        for(int16_t newx = 0; newx < newW; ++newx){
197
            uint8_t a = *(alp_new_buf+newx+newy*newW);
198
            graph_set_pixel_alpha(initx+newx,inity+newy,p->color, a);
199
        }
200
    }
201
    free(alp_new_buf);
202
    return SUCCESS;
203
}