1 /**
2  * @file lv_font.h
3  *
4  */
5 
6 #ifndef LV_FONT_FMT_TXT_H
7 #define LV_FONT_FMT_TXT_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #ifdef LV_CONF_INCLUDE_SIMPLE
17 #include "lv_conf.h"
18 #else
19 #include "../../lv_conf.h"
20 #endif
21 
22 #include <stdint.h>
23 #include <stddef.h>
24 #include <stdbool.h>
25 #include "lv_font.h"
26 
27 /*********************
28  *      DEFINES
29  *********************/
30 
31 /**********************
32  *      TYPEDEFS
33  **********************/
34 
35 /** This describes a glyph. */
36 typedef struct
37 {
38 #if LV_FONT_FMT_TXT_LARGE == 0
39     uint32_t bitmap_index : 20;     /**< Start index of the bitmap. A font can be max 1 MB. */
40     uint32_t adv_w :12;             /**< Draw the next glyph after this width. 8.4 format (real_value * 16 is stored). */
41 #else
42     uint32_t bitmap_index;          /**< Start index of the bitmap. A font can be max 4 GB. */
43     uint32_t adv_w;                 /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored). */
44 #endif
45     uint8_t box_w;                  /**< Width of the glyph's bounding box*/
46     uint8_t box_h;                  /**< Height of the glyph's bounding box*/
47     int8_t ofs_x;                   /**< x offset of the bounding box*/
48     uint8_t ofs_y;                  /**< y offset of the bounding box. Measured from the top of the line*/
49 }lv_font_fmt_txt_glyph_dsc_t;
50 
51 
52 /** Format of font character map. */
53 enum {
54     LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY,
55     LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL,
56     LV_FONT_FMT_TXT_CMAP_SPARSE_TINY,
57     LV_FONT_FMT_TXT_CMAP_SPARSE_FULL,
58 };
59 
60 typedef uint8_t lv_font_fmt_txt_cmap_type_t;
61 
62 
63 /* Map codepoints to a `glyph_dsc`s
64  * Several formats are supported to optimize memory usage
65  * See https://github.com/littlevgl/lv_font_conv/blob/master/doc/font_spec.md
66  */
67 typedef struct {
68     /** First Unicode character for this range */
69     uint32_t range_start;
70 
71     /** Number of Unicode characters related to this range.
72      * Last Unicode character = range_start + range_length - 1*/
73     uint16_t range_length;
74 
75     /** First glyph ID (array index of `glyph_dsc`) for this range */
76     uint16_t glyph_id_start;
77 
78     /*
79     According the specification there are 4 formats:
80         https://github.com/littlevgl/lv_font_conv/blob/master/doc/font_spec.md
81 
82     For simplicity introduce "relative code point":
83         rcp = codepoint - range_start
84 
85     and a search function:
86         search a "value" in an "array" and returns the index of "value".
87 
88     Format 0 tiny
89         unicode_list == NULL && glyph_id_ofs_list == NULL
90         glyph_id = glyph_id_start + rcp
91 
92     Format 0 full
93         unicode_list == NULL && glyph_id_ofs_list != NULL
94         glyph_id = glyph_id_start + glyph_id_ofs_list[rcp]
95 
96     Sparse tiny
97         unicode_list != NULL && glyph_id_ofs_list == NULL
98         glyph_id = glyph_id_start + search(unicode_list, rcp)
99 
100     Sparse full
101         unicode_list != NULL && glyph_id_ofs_list != NULL
102         glyph_id = glyph_id_start + glyph_id_ofs_list[search(unicode_list, rcp)]
103     */
104 
105     const uint16_t * unicode_list;
106 
107     /** if(type == LV_FONT_FMT_TXT_CMAP_FORMAT0_...) it's `uint8_t *`
108      * if(type == LV_FONT_FMT_TXT_CMAP_SPARSE_...)  it's `uint16_t *`
109      */
110     const void * glyph_id_ofs_list;
111 
112     /** Length of `unicode_list` and/or `glyph_id_ofs_list`*/
113     uint16_t list_length;
114 
115     /** Type of this character map*/
116     lv_font_fmt_txt_cmap_type_t type   :2;
117 }lv_font_fmt_txt_cmap_t;
118 
119 /** A simple mapping of kern values from pairs*/
120 typedef struct {
121     /*To get a kern value of two code points:
122        1. Get the `glyph_id_left` and `glyph_id_right` from `lv_font_fmt_txt_cmap_t
123        2  for(i = 0; i < pair_cnt * 2; i+2)
124              if(gylph_ids[i] == glyph_id_left &&
125                 gylph_ids[i+1] == glyph_id_right)
126                  return values[i / 2];
127      */
128     const void * glyph_ids;
129     const int8_t * values;
130     uint32_t pair_cnt   :24;
131     uint32_t glyph_ids_size :2;     /*0: `glyph_ids` is stored as `uint8_t`; 1: as `uint16_t`*/
132 }lv_font_fmt_txt_kern_pair_t;
133 
134 /** More complex but more optimal class based kern value storage*/
135 typedef struct {
136     /*To get a kern value of two code points:
137           1. Get the `glyph_id_left` and `glyph_id_right` from `lv_font_fmt_txt_cmap_t
138           2  Get the class of the left and right glyphs as `left_class` and `right_class`
139               left_class = left_class_mapping[glyph_id_left];
140               right_class = right_class_mapping[glyph_id_right];
141           3. value = class_pair_values[(left_class-1)*right_class_cnt + (righ_class-1)]
142         */
143 
144     const uint8_t * class_pair_values;    /*left_class_num * right_class_num value*/
145     const uint8_t * left_class_mapping;   /*Map the glyph_ids to classes: index -> glyph_id -> class_id*/
146     const uint8_t * right_class_mapping;  /*Map the glyph_ids to classes: index -> glyph_id -> class_id*/
147     uint8_t left_class_cnt;
148     uint8_t right_class_cnt;
149 }lv_font_fmt_txt_kern_classes_t;
150 
151 
152 /** Bitmap formats*/
153 typedef enum {
154     LV_FONT_FMT_TXT_PLAIN      = 0,
155     LV_FONT_FMT_TXT_COMPRESSED = 1,
156 }lv_font_fmt_txt_bitmap_format_t;
157 
158 
159 /*Describe store additional data for fonts */
160 typedef struct {
161     /*The bitmaps os all glyphs*/
162     const uint8_t * glyph_bitmap;
163 
164     /*Describe the glyphs*/
165     const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc;
166 
167     /* Map the glyphs to Unicode characters.
168      * Array of `lv_font_cmap_fmt_txt_t` variables*/
169     const lv_font_fmt_txt_cmap_t * cmaps;
170 
171     /* Store kerning values.
172      * Can be  `lv_font_fmt_txt_kern_pair_t *  or `lv_font_kern_classes_fmt_txt_t *`
173      * depending on `kern_classes`
174      */
175     const void * kern_dsc;
176 
177     /*Scale kern values in 12.4 format*/
178     uint16_t kern_scale;
179 
180     /*Number of cmap tables*/
181     uint16_t cmap_num       :10;
182 
183     /*Bit per pixel: 1, 2, 4 or 8*/
184     uint16_t bpp            :3;
185 
186     /*Type of `kern_dsc`*/
187     uint16_t kern_classes   :1;
188 
189     /*
190      * storage format of the bitmap
191      * from `lv_font_fmt_txt_bitmap_format_t`
192      */
193     uint16_t bitmap_format  :2;
194 
195     /*Cache the last letter and is glyph id*/
196     uint32_t last_letter;
197     uint32_t last_glyph_id;
198 
199 }lv_font_fmt_txt_dsc_t;
200 
201 /**********************
202  * GLOBAL PROTOTYPES
203  **********************/
204 
205 /**
206  * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed.
207  * @param font pointer to font
208  * @param unicode_letter an unicode letter which bitmap should be get
209  * @return pointer to the bitmap or NULL if not found
210  */
211 const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t letter);
212 
213 /**
214  * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed.
215  * @param font_p pointer to font
216  * @param dsc_out store the result descriptor here
217  * @param letter an UNICODE letter code
218  * @return true: descriptor is successfully loaded into `dsc_out`.
219  *         false: the letter was not found, no data is loaded to `dsc_out`
220  */
221 bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next);
222 
223 /**********************
224  *      MACROS
225  **********************/
226 
227 /**********************
228  * ADD BUILT IN FONTS
229  **********************/
230 
231 #ifdef __cplusplus
232 } /* extern "C" */
233 #endif
234 
235 #endif /*LV_FONT_FMT_TXT_H*/
236