root / proj / src / font.c @ 195
History | View | Annotate | Download (6.05 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 |
int good = false; |
76 |
char filepath[1024]; |
77 |
for(size_t i = 0; i < ret->nchars; ++i){ |
78 |
sprintf(filepath, "%s/ascii%03d.xpm2", s, i);
|
79 |
char **xpm = xpm_load_xpm2(filepath);
|
80 |
ret->glyphs[i] = glyph_ctor((const char**)xpm); |
81 |
if(ret->glyphs[i] != NULL) good = true; |
82 |
} |
83 |
if(good) return ret; |
84 |
else{
|
85 |
//font_dtor(ret);
|
86 |
return NULL; |
87 |
} |
88 |
} |
89 |
void (font_dtor)(font_t *p){
|
90 |
if(p == NULL) return; |
91 |
for(size_t i = 0; i < p->nchars; ++i) |
92 |
glyph_dtor(p->glyphs[i]); |
93 |
free(p->glyphs); |
94 |
free(p); |
95 |
} |
96 |
|
97 |
struct text{
|
98 |
const font_t *fnt;
|
99 |
char *txt;
|
100 |
int16_t x, y; |
101 |
int size;
|
102 |
uint32_t color; |
103 |
enum text_valign valign;
|
104 |
enum text_halign halign;
|
105 |
}; |
106 |
text_t* (text_ctor)(const font_t *fnt, const char *txt){ |
107 |
if(fnt == NULL) return NULL; |
108 |
text_t *ret = malloc(sizeof(text_t));
|
109 |
if(ret == NULL) return NULL; |
110 |
ret->fnt = fnt; |
111 |
ret->txt = NULL;
|
112 |
text_set_text(ret, txt); |
113 |
ret->x = 0;
|
114 |
ret->y = 0;
|
115 |
ret->size = 25;
|
116 |
ret->color = BLACK; |
117 |
ret->valign = text_valign_top; |
118 |
ret->halign = text_halign_left; |
119 |
return ret;
|
120 |
} |
121 |
void (text_dtor)(text_t *p){
|
122 |
if(p == NULL) return; |
123 |
free(p->txt); |
124 |
free(p); |
125 |
} |
126 |
void (text_set_text) (text_t *p, const char *txt){ |
127 |
size_t sz = strlen(txt); |
128 |
p->txt = realloc(p->txt, (sz+1)*sizeof(char)); |
129 |
if(p->txt == NULL) return; |
130 |
strcpy(p->txt, txt); |
131 |
} |
132 |
void (text_set_pos) (text_t *p, int16_t x, int16_t y ){ p->x = x; p->y = y; }
|
133 |
void (text_set_size) (text_t *p, unsigned size ){ p->size = size ; } |
134 |
void (text_set_color) (text_t *p, uint32_t color ){ p->color = color ; }
|
135 |
void (text_set_valign)(text_t *p, enum text_valign valign){ p->valign = valign; } |
136 |
void (text_set_halign)(text_t *p, enum text_halign halign){ p->halign = halign; } |
137 |
|
138 |
int (text_draw)(const text_t *p){ |
139 |
if(p == NULL) return NULL_PTR; |
140 |
int ret = SUCCESS;
|
141 |
// Get buffer with rescaled text
|
142 |
uint8_t *alp_new_buf = NULL;
|
143 |
uint16_t newH, newW;{ |
144 |
const size_t len = strlen(p->txt);
|
145 |
uint16_t W = 0, H = 0; { |
146 |
for(size_t i = 0; i < len; ++i){ |
147 |
const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
|
148 |
if(g != NULL){ W += g->w; H = max(H, g->h); } |
149 |
} |
150 |
} |
151 |
uint8_t *alp_buf = malloc(W*H); |
152 |
if(alp_buf == NULL) return ALLOC_ERROR;{ |
153 |
int16_t y = H; |
154 |
int16_t x = 0;
|
155 |
for(size_t i = 0; i < len; ++i){ |
156 |
const glyph_t *g = p->fnt->glyphs[(size_t)p->txt[i]];
|
157 |
if(g != NULL){ |
158 |
if((ret = glyph_draw_to_alpha_buffer(g, x, y, alp_buf, W, H))) return ret; |
159 |
x += g->w; |
160 |
} |
161 |
} |
162 |
} |
163 |
|
164 |
double factor = (double)p->size/(double)H; |
165 |
|
166 |
newH = H*factor; |
167 |
newW = W*factor; |
168 |
alp_new_buf = malloc(newW*newH); |
169 |
if(alp_new_buf == NULL) return ALLOC_ERROR; |
170 |
|
171 |
for(size_t newy = 0; newy < newH; ++newy){ |
172 |
size_t y = newy/factor; |
173 |
for(size_t newx = 0; newx < newW; ++newx){ |
174 |
size_t x = newx/factor; |
175 |
*(alp_new_buf+newx+newy*newW) = *(alp_buf+x+y*W); |
176 |
} |
177 |
} |
178 |
free(alp_buf); |
179 |
|
180 |
|
181 |
} |
182 |
// Get initial value of x
|
183 |
int16_t initx;{ |
184 |
switch(p->halign){
|
185 |
case text_halign_left : initx = p->x ; break; |
186 |
case text_halign_center: initx = p->x - newW/2; break; |
187 |
case text_halign_right : initx = p->x - newW ; break; |
188 |
default: return LOGIC_ERROR; |
189 |
} |
190 |
} |
191 |
// Get initial value of y
|
192 |
int16_t inity;{ |
193 |
switch(p->valign){
|
194 |
case text_valign_top : inity = p->y ; break; |
195 |
case text_valign_center: inity = p->y - newH/2; break; |
196 |
case text_valign_bottom: inity = p->y - newH ; break; |
197 |
default: return LOGIC_ERROR; |
198 |
} |
199 |
} |
200 |
// Draw text
|
201 |
for(int16_t newy = 0; newy < newH; ++newy){ |
202 |
for(int16_t newx = 0; newx < newW; ++newx){ |
203 |
uint8_t a = *(alp_new_buf+newx+newy*newW); |
204 |
graph_set_pixel_alpha(initx+newx,inity+newy,p->color, a); |
205 |
} |
206 |
} |
207 |
free(alp_new_buf); |
208 |
return SUCCESS;
|
209 |
} |