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
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
37GF_DECLARE_TYPE(font_store, {
38 int glyph_index;
39 int line_index;
40 unsigned char* buffer;
41});
42
46void gf_font_parse_line(gf_draw_t* draw, const char* path, gf_font_store_t* store, gf_font_t* font, char* line) {
47 int i;
48 char* args[32];
49 int argc = 0;
50 int incr = 0;
51 int dq = 0;
52 for(i = 0;; i++) {
53 if((dq == 0 && line[i] == ' ') || line[i] == 0) {
54 char oldc = line[i];
55 line[i] = 0;
56
57 args[argc] = line + incr;
58 if(args[argc][0] == '"') args[argc]++;
59 if(args[argc][strlen(args[argc]) - 1] == '"') args[argc][strlen(args[argc]) - 1] = 0;
60
61 argc++;
62
63 incr = i + 1;
64
65 if(oldc == 0) break;
66 } else if(line[i] == '"') {
67 dq = 1 - dq;
68 }
69 }
70 if(store->line_index != -1 && store->line_index < font->glyph[store->glyph_index]->bbox.height) {
71 int wid = font->glyph[store->glyph_index]->bbox.width;
72 unsigned char* linebuf = store->buffer + store->line_index * wid * 4;
73 for(i = 0; line[i] != 0; i++) {
74 int n = 0;
75 int j;
76 if('0' <= line[i] && line[i] <= '9') {
77 n = line[i] - '0';
78 } else if('a' <= line[i] && line[i] <= 'f') {
79 n = 10 + line[i] - 'a';
80 } else if('A' <= line[i] && line[i] <= 'F') {
81 n = 10 + line[i] - 'A';
82 }
83 for(j = 0; j < (wid > 4 ? 4 : wid); j++) {
84 if((n >> 3) & 1) {
85 memset(linebuf + 16 * i + 4 * j, 255, 4);
86 }
87 n = n << 1;
88 }
89 wid -= 4;
90 }
91 store->line_index++;
92 } else if(argc > 0 && strcmp(args[0], "STARTCHAR") == 0) {
93 font->glyph[store->glyph_index] = malloc(sizeof(**font->glyph));
94 memset(font->glyph[store->glyph_index], 0, sizeof(**font->glyph));
95 } else if(argc > 0 && strcmp(args[0], "ENDCHAR") == 0) {
96 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);
97 free(store->buffer);
98 store->glyph_index++;
99 store->line_index = -1;
100 } else if(argc > 0 && strcmp(args[0], "BITMAP") == 0) {
101 store->line_index = 0;
102 } else if(argc == 2) {
103 if(strcmp(args[0], "COPYRIGHT") == 0) {
104 gf_log_function(NULL, "%s: %s", path, args[1]);
105 } else if(strcmp(args[0], "NOTICE") == 0) {
106 gf_log_function(NULL, "%s: %s", path, args[1]);
107 } else if(strcmp(args[0], "FOUNDRY") == 0) {
108 gf_log_function(NULL, "%s: Made by %s", path, args[1]);
109 } else if(strcmp(args[0], "CHARS") == 0) {
110 int j;
111 gf_log_function(NULL, "%s: %s characters", path, args[1]);
112 font->count = atoi(args[1]);
113 font->glyph = malloc(font->count * sizeof(*font->glyph));
114 for(j = 0; j < font->count; j++) font->glyph[j] = NULL;
115 } else if(strcmp(args[0], "ENCODING") == 0) {
116 font->glyph[store->glyph_index]->code = atoi(args[1]);
117 }
118 } else if(argc == 3) {
119 if(strcmp(args[0], "DWIDTH") == 0) {
120 font->glyph[store->glyph_index]->dwidth[0] = atoi(args[1]);
121 font->glyph[store->glyph_index]->dwidth[1] = atoi(args[2]);
122 }
123 } else if(argc == 5) {
124 if(strcmp(args[0], "FONTBOUNDINGBOX") == 0) {
125 font->bbox.width = atoi(args[1]);
126 font->bbox.height = atoi(args[2]);
127 font->bbox.x = atoi(args[3]);
128 font->bbox.y = atoi(args[4]);
129 } else if(strcmp(args[0], "BBX") == 0) {
130 font->glyph[store->glyph_index]->bbox.width = atoi(args[1]);
131 font->glyph[store->glyph_index]->bbox.height = atoi(args[2]);
132 font->glyph[store->glyph_index]->bbox.x = atoi(args[3]);
133 font->glyph[store->glyph_index]->bbox.y = atoi(args[4]);
134
135 store->buffer = malloc(atoi(args[1]) * atoi(args[2]) * 4);
136 memset(store->buffer, 0, atoi(args[1]) * atoi(args[2]) * 4);
137 }
138 }
139}
140
141gf_font_t* gf_font_create(gf_draw_t* draw, const char* path) {
142 gf_font_t* font = malloc(sizeof(*font));
143 struct gf_stat s;
144 char* buf;
145 FILE* f;
146 int i = 0;
147 int incr = 0;
148 gf_font_store_t store;
149 store.line_index = -1;
150 store.glyph_index = 0;
151 memset(font, 0, sizeof(*font));
152 if(gf_stat(path, &s) != 0) {
153 free(font);
154 return NULL;
155 }
156 gf_log_function(NULL, "%s: %lu bytes", path, (unsigned long)s.st_size);
157 buf = malloc(s.st_size + 1);
158 buf[s.st_size] = 0;
159 f = fopen(path, "r");
160 fread(buf, s.st_size, 1, f);
161 fclose(f);
162
163 for(i = 0;; i++) {
164 if(buf[i] == 0 || buf[i] == '\n') {
165 char oldc = buf[i];
166 char* line = buf + incr;
167 buf[i] = 0;
168 incr = i + 1;
169
170 gf_font_parse_line(draw, path, &store, font, line);
171
172 if(oldc == 0) break;
173 }
174 }
175
176 free(buf);
177 return font;
178}
gf_font_t * gf_font_create(gf_draw_t *draw, const char *path)
Load font.
Definition gf_font.c:141
gf_font_glyph_t * gf_font_get(gf_font_t *font, int code)
Get glyph.
Definition gf_font.c:20
Logger.
#define gf_log_function(engine, fmt,...)
Output log with line number and function name.
Definition gf_log.h:26
#define GF_DECLARE_TYPE(n, b)
Macro to define engine type shorter.
Definition gf_macro.h:180
Required headers before anything.
Texture.
gf_texture_t * gf_texture_create(gf_draw_t *draw, int width, int height, unsigned char *data)
Create texture.
Definition gf_texture.c:17
Drawing interface.
Definition draw.h:108
int y
Y coord.
Definition font.h:47
int width
Width.
Definition font.h:47
int x
X coord.
Definition font.h:47
int height
Height.
Definition font.h:47
Glyph.
Definition font.h:75
int code
Character code.
Definition font.h:75
int dwidth[2]
Device width.
Definition font.h:75
gf_font_bbox_t bbox
Bounding box.
Definition font.h:75
gf_texture_t * texture
Texture.
Definition font.h:75
Font.
Definition font.h:95
gf_font_glyph_t ** glyph
Glyph data.
Definition font.h:95
int count
Glyph count.
Definition font.h:95
gf_font_bbox_t bbox
Bounding box.
Definition font.h:95