GoldFish Engine
Quite simple and lightweight game engine
Loading...
Searching...
No Matches
gf_font.c
1#define GF_EXPOSE_FONT
2
3#include <gf_pre.h>
4
5/* External library */
6
7/* Interface */
8#include <gf_font.h>
9
10/* Engine */
11#include <gf_log.h>
12#include <gf_texture.h>
13
14/* Standard */
15#include <sys/stat.h>
16#include <string.h>
17#include <stdlib.h>
18#include <stdio.h>
19
20gf_font_glyph_t* gf_font_get(gf_font_t* font, int code) {
21 int i;
22 if(code < 0x20) return NULL;
23 for(i = 0; i < font->count; i++) {
24 if(font->glyph[i] != NULL && font->glyph[i]->code == code) {
25 return font->glyph[i];
26 }
27 }
28 return NULL;
29}
30
31#ifdef _MSC_VER
32#define gf_stat _stat
33#else
34#define gf_stat stat
35#endif
36
40void gf_font_parse_line(gf_draw_t* draw, const char* path, gf_font_store_t* store, gf_font_t* font, char* line) {
41 int i;
42 char* args[32];
43 int argc = 0;
44 int incr = 0;
45 int dq = 0;
46 for(i = 0;; i++) {
47 if((dq == 0 && line[i] == ' ') || line[i] == 0) {
48 char oldc = line[i];
49 line[i] = 0;
50
51 args[argc] = line + incr;
52 if(args[argc][0] == '"') args[argc]++;
53 if(args[argc][strlen(args[argc]) - 1] == '"') args[argc][strlen(args[argc]) - 1] = 0;
54
55 argc++;
56
57 incr = i + 1;
58
59 if(oldc == 0) break;
60 } else if(line[i] == '"') {
61 dq = 1 - dq;
62 }
63 }
64 if(store->line_index != -1 && store->line_index < font->glyph[store->glyph_index]->bbox.height) {
65 int wid = font->glyph[store->glyph_index]->bbox.width;
66 unsigned char* linebuf = store->buffer + store->line_index * wid * 4;
67 for(i = 0; line[i] != 0; i++) {
68 int n = 0;
69 int j;
70 if('0' <= line[i] && line[i] <= '9') {
71 n = line[i] - '0';
72 } else if('a' <= line[i] && line[i] <= 'f') {
73 n = 10 + line[i] - 'a';
74 } else if('A' <= line[i] && line[i] <= 'F') {
75 n = 10 + line[i] - 'A';
76 }
77 for(j = 0; j < (wid > 4 ? 4 : wid); j++) {
78 if((n >> 3) & 1) {
79 memset(linebuf + 16 * i + 4 * j, 255, 4);
80 }
81 n = n << 1;
82 }
83 wid -= 4;
84 }
85 store->line_index++;
86 } else if(argc > 0 && strcmp(args[0], "STARTCHAR") == 0) {
87 font->glyph[store->glyph_index] = malloc(sizeof(**font->glyph));
88 memset(font->glyph[store->glyph_index], 0, sizeof(**font->glyph));
89 } else if(argc > 0 && strcmp(args[0], "ENDCHAR") == 0) {
90 font->glyph[store->glyph_index]->texture = gf_texture_create(draw, font->glyph[store->glyph_index]->bbox.width, font->glyph[store->glyph_index]->bbox.height, store->buffer);
91 free(store->buffer);
92 store->glyph_index++;
93 store->line_index = -1;
94 } else if(argc > 0 && strcmp(args[0], "BITMAP") == 0) {
95 store->line_index = 0;
96 } else if(argc == 2) {
97 if(strcmp(args[0], "COPYRIGHT") == 0) {
98 gf_log_function(NULL, "%s: %s", path, args[1]);
99 } else if(strcmp(args[0], "NOTICE") == 0) {
100 gf_log_function(NULL, "%s: %s", path, args[1]);
101 } else if(strcmp(args[0], "FOUNDRY") == 0) {
102 gf_log_function(NULL, "%s: Made by %s", path, args[1]);
103 } else if(strcmp(args[0], "CHARS") == 0) {
104 int j;
105 gf_log_function(NULL, "%s: %s characters", path, args[1]);
106 font->count = atoi(args[1]);
107 font->glyph = malloc(font->count * sizeof(*font->glyph));
108 for(j = 0; j < font->count; j++) font->glyph[j] = NULL;
109 } else if(strcmp(args[0], "ENCODING") == 0) {
110 font->glyph[store->glyph_index]->code = atoi(args[1]);
111 }
112 } else if(argc == 3) {
113 if(strcmp(args[0], "DWIDTH") == 0) {
114 font->glyph[store->glyph_index]->dwidth[0] = atoi(args[1]);
115 font->glyph[store->glyph_index]->dwidth[1] = atoi(args[2]);
116 }
117 } else if(argc == 5) {
118 if(strcmp(args[0], "FONTBOUNDINGBOX") == 0) {
119 font->bbox.width = atoi(args[1]);
120 font->bbox.height = atoi(args[2]);
121 font->bbox.x = atoi(args[3]);
122 font->bbox.y = atoi(args[4]);
123 } else if(strcmp(args[0], "BBX") == 0) {
124 font->glyph[store->glyph_index]->bbox.width = atoi(args[1]);
125 font->glyph[store->glyph_index]->bbox.height = atoi(args[2]);
126 font->glyph[store->glyph_index]->bbox.x = atoi(args[3]);
127 font->glyph[store->glyph_index]->bbox.y = atoi(args[4]);
128
129 store->buffer = malloc(atoi(args[1]) * atoi(args[2]) * 4);
130 memset(store->buffer, 0, atoi(args[1]) * atoi(args[2]) * 4);
131 }
132 }
133}
134
135gf_font_t* gf_font_create_raw(gf_draw_t* draw, const char* path, const void* data, size_t size) {
136 gf_font_t* font = malloc(sizeof(*font));
137 char* buf;
138 int i = 0;
139 int incr = 0;
140 gf_font_store_t store;
141 store.line_index = -1;
142 store.glyph_index = 0;
143 memset(font, 0, sizeof(*font));
144
145 buf = malloc(size + 1);
146 buf[size] = 0;
147 memcpy(buf, data, size);
148
149 for(i = 0;; i++) {
150 if(buf[i] == 0 || buf[i] == '\n') {
151 char oldc = buf[i];
152 char* line = buf + incr;
153 buf[i] = 0;
154 incr = i + 1;
155
156 gf_font_parse_line(draw, path, &store, font, line);
157
158 if(oldc == 0) break;
159 }
160 }
161
162 free(buf);
163 return font;
164}
165
166gf_font_t* gf_font_create(gf_draw_t* draw, const char* path) {
167 FILE* f;
168 struct gf_stat s;
169 char* buf;
170 gf_font_t* font;
171 if(gf_stat(path, &s) != 0) {
172 return NULL;
173 }
174 gf_log_function(NULL, "%s: %lu bytes", path, (unsigned long)s.st_size);
175 buf = malloc(s.st_size + 1);
176 buf[s.st_size] = 0;
177 f = fopen(path, "r");
178 fread(buf, s.st_size, 1, f);
179 fclose(f);
180
181 font = gf_font_create_raw(draw, path, buf, s.st_size);
182
183 free(buf);
184
185 return font;
186}
187
188void gf_font_destroy(gf_font_t* font) {
189 int i;
190 for(i = 0; i < font->count; i++) {
191 gf_texture_destroy(font->glyph[i]->texture);
192 }
193 free(font->glyph);
194 free(font);
195}
Logger.
#define gf_log_function(engine, fmt,...)
Output log with line number and function name.
Definition gf_log.h:26
Required headers before anything.
Texture.
Drawing interface.
Definition draw.h:108
int y
Y coord.
Definition font.h:67
int width
Width.
Definition font.h:67
int x
X coord.
Definition font.h:67
int height
Height.
Definition font.h:67
Glyph.
Definition font.h:95
int code
Character code.
Definition font.h:95
int dwidth[2]
Device width.
Definition font.h:95
gf_font_bbox_t bbox
Bounding box.
Definition font.h:95
gf_texture_t * texture
Texture.
Definition font.h:95
Internal struct used for parsing.
Definition font.h:43
int glyph_index
Current glyph index.
Definition font.h:43
unsigned char * buffer
Glyph buffer.
Definition font.h:43
Font.
Definition font.h:115
gf_font_glyph_t ** glyph
Glyph data.
Definition font.h:115
int count
Glyph count.
Definition font.h:115
gf_font_bbox_t bbox
Bounding box.
Definition font.h:115