You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
5.5 KiB

  1. # QMK Font Format :id=qmk-font-format
  2. QMK uses a font format _("Quantum Font Format" - QFF)_ specifically for resource-constrained systems.
  3. This format is capable of encoding 1-, 2-, 4-, and 8-bit-per-pixel greyscale- and palette-based images into a font. It also includes RLE for pixel data for some basic compression.
  4. All integer values are in little-endian format.
  5. The QFF is defined in terms of _blocks_ -- each _block_ contains a _header_ and an optional _blob_ of data. The _header_ contains the block's _typeid_, and the length of the _blob_ that follows. Each block type is denoted by a different _typeid_ has its own block definition below. All blocks are defined as packed structs, containing zero padding between fields.
  6. The general structure of the file is:
  7. * _Font descriptor block_
  8. * _ASCII glyph block_ (optional, only if ASCII glyphs are included)
  9. * _Unicode glyph block_ (optional, only if Unicode glyphs are included)
  10. * _Font palette block_ (optional, depending on frame format)
  11. * _Font data block_
  12. ## Block Header :id=qff-block-header
  13. The block header is identical to [QGF's block header](quantum_painter_qgf.md#qgf-block-header), and is present for all blocks, including the font descriptor.
  14. ## Font descriptor block :id=qff-font-descriptor
  15. * _typeid_ = 0x00
  16. * _length_ = 20
  17. This block must be located at the start of the file contents, and can exist a maximum of once in an entire QGF file. It is always followed by either the _ASCII glyph table_ or the _Unicode glyph table_, depending on which glyphs are included in the font.
  18. _Block_ format:
  19. ```c
  20. typedef struct __attribute__((packed)) qff_font_descriptor_v1_t {
  21. qgf_block_header_v1_t header; // = { .type_id = 0x00, .neg_type_id = (~0x00), .length = 20 }
  22. uint24_t magic; // constant, equal to 0x464651 ("QFF")
  23. uint8_t qff_version; // constant, equal to 0x01
  24. uint32_t total_file_size; // total size of the entire file, starting at offset zero
  25. uint32_t neg_total_file_size; // negated value of total_file_size, used for detecting parsing errors
  26. uint8_t line_height; // glyph height in pixels
  27. bool has_ascii_table; // whether the font has an ascii table of glyphs (0x20...0x7E)
  28. uint16_t num_unicode_glyphs; // the number of glyphs in the unicode table -- no table specified if zero
  29. uint8_t format; // frame format, see below.
  30. uint8_t flags; // frame flags, see below.
  31. uint8_t compression_scheme; // compression scheme, see below.
  32. uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented)
  33. } qff_font_descriptor_v1_t;
  34. // _Static_assert(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
  35. ```
  36. The values for `format`, `flags`, `compression_scheme`, and `transparency_index` match [QGF's frame descriptor block](quantum_painter_qgf.md#qgf-frame-descriptor), with the exception that the `delta` flag is ignored by QFF.
  37. ## ASCII glyph table :id=qff-ascii-table
  38. * _typeid_ = 0x01
  39. * _length_ = 290
  40. If the font contains ascii characters, the _ASCII glyph block_ must be located directly after the _font descriptor block_.
  41. ```c
  42. #define QFF_GLYPH_WIDTH_BITS 6
  43. #define QFF_GLYPH_WIDTH_MASK ((1<<QFF_GLYPH_WIDTH_BITS)-1)
  44. #define QFF_GLYPH_OFFSET_BITS 18
  45. #define QFF_GLYPH_OFFSET_MASK (((1<<QFF_GLYPH_OFFSET_BITS)-1) << QFF_GLYPH_WIDTH_BITS)
  46. typedef struct __attribute__((packed)) qff_ascii_glyph_table_v1_t {
  47. qgf_block_header_v1_t header; // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = 285 }
  48. uint24_t glyph[95]; // 95 glyphs, 0x20..0x7E, see bits/masks above for values
  49. } qff_ascii_glyph_table_v1_t;
  50. // _Static_assert(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + 285), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
  51. ```
  52. ## Unicode glyph table :id=qff-unicode-table
  53. * _typeid_ = 0x02
  54. * _length_ = variable
  55. If this font contains unicode characters, the _unicode glyph block_ must be located directly after the _ASCII glyph table block_, or the _font descriptor block_ if the font does not contain ASCII characters.
  56. ```c
  57. typedef struct __attribute__((packed)) qff_unicode_glyph_table_v1_t {
  58. qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = (N * 6) }
  59. struct __attribute__((packed)) { // container for a single unicode glyph
  60. uint24_t code_point; // the unicode code point
  61. uint24_t glyph; // the glyph information, as per ASCII glyphs above
  62. } glyph[N]; // N glyphs worth of data
  63. } qff_unicode_glyph_table_v1_t;
  64. ```
  65. ## Font palette block :id=qff-palette-descriptor
  66. * _typeid_ = 0x03
  67. * _length_ = variable
  68. The _font palette block_ is identical to [QGF's frame palette block](quantum_painter_qgf.md#qgf-frame-palette-descriptor), retaining the same _typeid_ of 0x03.
  69. It is only specified in the QFF if the font is palette-based, and follows the _unicode glyph block_ if the font contains any Unicode glyphs, or the _ASCII glyph block_ if the font contains only ASCII glyphs.
  70. ## Font data block :id=qff-data-descriptor
  71. * _typeid_ = 0x04
  72. * _length_ = variable
  73. The _font data block_ is the last block in the file and is identical to [QGF's frame data block](quantum_painter_qgf.md#qgf-frame-data-descriptor), however has a different _typeid_ of 0x04 in QFF.