summaryrefslogtreecommitdiff
path: root/src/user/libfont/bdf.c
blob: 2c19a15c3eee4058c1550d0787fb5d44f091abcb (plain) (blame)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <libfont/fonts.h>

#include <knob/format.h>
#include <knob/panic.h>
#include <knob/block.h>
#include <knob/heap.h>
#include <knob/file.h>

#include <stdbool.h>
#include <stdint.h>

#define LINE_BUF_SIZE 1000
char line_buf[LINE_BUF_SIZE];

static inline uint8_t hex_to_n(char ch) {
  return ch - (ch >= 'A' ? 'A' - 10 : '0');
}

//very minimal implementation
bool try_load_bdf(const char *path, struct font_info *into) {
  struct file *f = open_file(path);
  if (!f)
    PANIC("Can't open font file sent by get_font.");

  read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1);
  if (!strequ(line_buf, "STARTFONT 2.1")) {
    close_file(f);
    return false;
  }

  for (uint16_t i = 0; i < 256; ++i)
    into->bitmaps[i] = 0;
  into->space_height = -1;
  into->space_width = -1;
  into->char_height = -1;
  into->char_width = -1;

  uint32_t current = 0;

  while (read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1)) {
    if (blockequ(line_buf, "FONTBOUNDINGBOX ", 16)) {
      uint32_t n;
      uint32_t l = try_swtou(line_buf + 16, &n);
      if (!l)
        goto bad_format;
      into->space_width = n;
      into->char_width = n;
      l = try_swtou(line_buf + 16 + l, &n);
      if (!l)
        goto bad_format;
      into->space_height = n;
      into->char_height = n;
    }
    else if (blockequ(line_buf, "ENCODING ", 9)) {
      if (!try_swtou(line_buf + 9, &current))
        goto bad_format;
    }
    else if (strequ(line_buf, "BITMAP")) {
      if (current >= 256)
        continue;
      bool *bm = get_block(into->char_height * into->char_width);
      if (!bm)
        PANIC("could not allocate memory for font character bitmap");
      into->bitmaps[current] = bm;

      for (uint32_t y = 0; y < into->char_height; ++y) {
        read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1);
        for (uint32_t x = 0; x < into->char_width; ++x)
          bm[y * into->char_width + x] = (hex_to_n(line_buf[x / 4]) >> (3 - x % 4)) & 1;
      }
    }
  }

  close_file(f);
  f = 0;

  if ((into->char_height  == -1) ||
      (into->char_width   == -1) ||
      (into->space_height == -1) ||
      (into->space_width  == -1))
    goto bad_format;

  if (!into->bitmaps[0]) {
    const uint32_t bytes = (into->char_height * into->char_width - 1) / 8 + 1;
    into->bitmaps[0] = get_block(bytes);
    for (uint32_t i = 0; i < bytes; ++i)
      into->bitmaps[0][i] = 0b01011010;
  }

  return true;

bad_format:
  if (f)
    close_file(f);
  for (uint16_t i = 0; i < 256; ++i)
    if (into->bitmaps[i])
      free_block(into->bitmaps[i]);
  return false;
}