-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathserialize_font.c
More file actions
78 lines (73 loc) · 3.04 KB
/
serialize_font.c
File metadata and controls
78 lines (73 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <ctype.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "convfont.h"
#include "serialize_font.h"
/* Compute the total size, in bytes, a font will be.
* @param font A pointer to the font to find the size of
* @return The size of the font */
int compute_font_size(fontlib_font_t *font) {
int size = 18;
size += 3 * font->total_glyphs;
for (int i = 0; i < font->total_glyphs; i++)
size += font->bitmaps[i]->length;
return size;
}
/* The idea of this system with an output callback with custom_data is that you
* can specify how exactly to output data. For an output binary file, you can
* pass a wrapper for fputc(); for a static C or assembly array, you can have it
* produce hex bytes. */
void output_word(uint16_t data, void(*output)(uint8_t byte, void *custom_data), void *custom_data) {
output((uint8_t)(data & 255), custom_data);
output((uint8_t)(data >> 8), custom_data);
}
void output_ezword(uint32_t data, void(*output)(uint8_t byte, void *custom_data), void *custom_data) {
output((uint8_t)(data & 255), custom_data);
output((uint8_t)((data >> 8) & 255), custom_data);
output((uint8_t)((data >> 16) & 255), custom_data);
}
/* Serializes a FontLib font into bytes.
* @param font The font to serialize
* @param output A function to use to serialize the bytes. custom_data can be
* any data you like, such a FILE struct.
*/
void serialize_font(fontlib_font_t *font, void(*output)(uint8_t byte, void *custom_data), void *custom_data) {
/* Write header */
output(font->fontVersion, custom_data);
output(font->height, custom_data);
output(font->total_glyphs & 0xFF, custom_data);
output(font->first_glyph, custom_data);
/* These values come from the data format */
output_ezword(18, output, custom_data);
int next_bitmap_offset = 18 + font->total_glyphs;
output_ezword(next_bitmap_offset, output, custom_data);
/* More header */
output(font->italic_space_adjust, custom_data);
output(font->space_above, custom_data);
output(font->space_below, custom_data);
output(font->weight, custom_data);
output(font->style, custom_data);
output(font->cap_height, custom_data);
output(font->x_height, custom_data);
output(font->baseline_height, custom_data);
/* Populate widths table */
for (int i = 0; i < font->total_glyphs; i++)
output(font->widths_table[i], custom_data);
/* Populate bitmaps offsets table */
next_bitmap_offset += font->total_glyphs * 2;
for (int i = 0; i < font->total_glyphs; i++) {
output_word((uint16_t)(next_bitmap_offset - 2 + (byte_columns(font->widths_table[i]) - 1)), output, custom_data);
next_bitmap_offset += font->bitmaps[i]->length;
if (next_bitmap_offset >= MAX_APPVAR_SIZE)
throw_error(invalid_fnt, "Output font too big to fit!");
}
/* Start writing glyph bitmaps */
for (int i = 0; i < font->total_glyphs; i++)
for (int y = 0; y < font->height; y++) {
int columns = byte_columns(font->widths_table[i]);
for (int c = columns - 1; c >= 0; c--)
output(font->bitmaps[i]->bytes[y * columns + c], custom_data);
}
}