bmp: Rewrote the RLE decompressor
[deark.git] / modules / unifont.c
bloba25bcda1c09bafca7dc8bf11eebf25939d5982b2
1 // This file is part of Deark.
2 // Copyright (C) 2018 Jason Summers
3 // See the file COPYING for terms of use.
5 // Unifont HEX font
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_unifont_hex);
11 struct de_linereader {
12 dbuf *f;
13 i64 f_pos;
16 static struct de_linereader *de_linereader_create(deark *c, dbuf *f)
18 struct de_linereader *lr;
19 lr = de_malloc(c, sizeof(struct de_linereader));
20 lr->f = f;
21 return lr;
24 static void de_linereader_destroy(deark *c, struct de_linereader *lr)
26 if(!lr) return;
27 de_free(c, lr);
30 // TODO: Make the linereader more efficient and flexible, and make
31 // it a standard library function.
32 static int de_linereader_readnextline(deark *c, struct de_linereader *lr,
33 char *buf, size_t buf_len, unsigned int flags)
35 int ret;
36 i64 content_len = 0;
37 i64 total_len = 0;
39 buf[0] = '\0';
41 ret = dbuf_find_line(lr->f, lr->f_pos, &content_len, &total_len);
42 if(!ret) return 0;
43 if(content_len > (i64)buf_len-1) {
44 lr->f_pos += total_len;
45 return 0;
47 dbuf_read(lr->f, (u8*)buf, lr->f_pos, content_len);
48 buf[content_len] = '\0';
49 lr->f_pos += total_len;
50 return 1;
53 static void decode_fontdata(deark *c, const char *hexdata,
54 struct de_bitmap_font_char *ch)
56 i64 ndstbytes;
57 i64 srcpos = 0;
58 i64 dstpos = 0;
60 ndstbytes = ch->rowspan*ch->height;
61 while(1) {
62 int errorflag;
63 u8 h0, h1;
65 h0 = de_decode_hex_digit((unsigned char)hexdata[srcpos++], &errorflag);
66 if(errorflag) break;
67 h1 = de_decode_hex_digit((unsigned char)hexdata[srcpos++], &errorflag);
68 if(errorflag) break;
69 ch->bitmap[dstpos++] = (h0<<4)|h1;
70 if(dstpos>=ndstbytes) break;
74 static void de_run_unifont_hex(deark *c, de_module_params *mparams)
76 struct de_bitmap_font *font = NULL;
77 i64 char_array_numalloc = 0;
78 char linebuf[256];
79 struct de_linereader *lr = NULL;
80 int ok = 0;
82 font = de_create_bitmap_font(c);
83 font->has_unicode_codepoints = 1;
84 font->prefer_unicode = 1;
85 font->nominal_height = 16;
86 char_array_numalloc = 1024;
87 font->char_array = de_mallocarray(c, char_array_numalloc, sizeof(struct de_bitmap_font_char));
89 lr = de_linereader_create(c, c->infile);
91 while(de_linereader_readnextline(c, lr, linebuf, sizeof(linebuf), 0)) {
92 i64 idx;
93 struct de_bitmap_font_char *ch;
94 i64 fdata_len;
95 char *dptr; // Pointer into linebuf, to the char after the ":"
97 if(font->num_chars>=17*65536) goto done;
99 idx = font->num_chars;
100 if(idx >= char_array_numalloc) {
101 i64 new_numalloc = char_array_numalloc*2;
102 font->char_array = de_reallocarray(c, font->char_array,
103 char_array_numalloc, sizeof(struct de_bitmap_font_char),
104 new_numalloc);
105 char_array_numalloc = new_numalloc;
107 ch = &font->char_array[idx];
109 dptr = de_strchr(linebuf, ':');
110 if(!dptr) goto done;
111 *dptr = '\0';
112 dptr++;
114 fdata_len = (i64)de_strlen(dptr);
115 ch->codepoint_unicode = (i32)de_strtoll(linebuf, NULL, 16);
116 if(ch->codepoint_unicode<0 || ch->codepoint_unicode>=17*65536) goto done;
118 ch->width = (int)((fdata_len/32)*8);
119 ch->height = 16;
120 de_dbg2(c, "char[%d] U+%04X %d"DE_CHAR_TIMES"%d",
121 (int)font->num_chars, (unsigned int)ch->codepoint_unicode,
122 ch->width, ch->height);
123 if(ch->width<8 || ch->width>32) goto done;
124 ch->rowspan = (ch->width+7)/8;
125 ch->bitmap = de_malloc(c, ch->rowspan * ch->height);
126 decode_fontdata(c, dptr, ch);
128 font->num_chars++;
129 if(ch->width > font->nominal_width) {
130 font->nominal_width = ch->width;
134 de_dbg(c, "number of characters: %d", (int)font->num_chars);
135 if(font->num_chars<1) goto done;
136 if(font->nominal_width<1) goto done;
138 de_font_bitmap_font_to_image(c, font, NULL, 0);
139 ok = 1;
141 done:
142 if(!ok) {
143 de_err(c, "Error parsing HEX font file (offset %"I64_FMT")", lr->f_pos);
145 de_linereader_destroy(c, lr);
146 if(font) {
147 if(font->char_array) {
148 i64 k;
149 for(k=0; k<font->num_chars; k++) {
150 de_free(c, font->char_array[k].bitmap);
152 de_free(c, font->char_array);
154 font->char_array = NULL;
155 de_destroy_bitmap_font(c, font);
159 void de_module_unifont_hex(deark *c, struct deark_module_info *mi)
161 mi->id = "unifont_hex";
162 mi->desc = "GNU Unifont HEX font";
163 mi->run_fn = de_run_unifont_hex;