acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_font_loader.c (21365B)
1 /** 2 * @file lv_font_loader.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 10 #include <stdint.h> 11 #include <stdbool.h> 12 13 #include "../lvgl.h" 14 #include "../misc/lv_fs.h" 15 #include "lv_font_loader.h" 16 17 /********************** 18 * TYPEDEFS 19 **********************/ 20 typedef struct { 21 lv_fs_file_t * fp; 22 int8_t bit_pos; 23 uint8_t byte_value; 24 } bit_iterator_t; 25 26 typedef struct font_header_bin { 27 uint32_t version; 28 uint16_t tables_count; 29 uint16_t font_size; 30 uint16_t ascent; 31 int16_t descent; 32 uint16_t typo_ascent; 33 int16_t typo_descent; 34 uint16_t typo_line_gap; 35 int16_t min_y; 36 int16_t max_y; 37 uint16_t default_advance_width; 38 uint16_t kerning_scale; 39 uint8_t index_to_loc_format; 40 uint8_t glyph_id_format; 41 uint8_t advance_width_format; 42 uint8_t bits_per_pixel; 43 uint8_t xy_bits; 44 uint8_t wh_bits; 45 uint8_t advance_width_bits; 46 uint8_t compression_id; 47 uint8_t subpixels_mode; 48 uint8_t padding; 49 int16_t underline_position; 50 uint16_t underline_thickness; 51 } font_header_bin_t; 52 53 typedef struct cmap_table_bin { 54 uint32_t data_offset; 55 uint32_t range_start; 56 uint16_t range_length; 57 uint16_t glyph_id_start; 58 uint16_t data_entries_count; 59 uint8_t format_type; 60 uint8_t padding; 61 } cmap_table_bin_t; 62 63 /********************** 64 * STATIC PROTOTYPES 65 **********************/ 66 static bit_iterator_t init_bit_iterator(lv_fs_file_t * fp); 67 static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font); 68 int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t format, uint32_t start); 69 70 static int read_bits_signed(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); 71 static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); 72 73 /********************** 74 * MACROS 75 **********************/ 76 77 /********************** 78 * GLOBAL FUNCTIONS 79 **********************/ 80 81 /** 82 * Loads a `lv_font_t` object from a binary font file 83 * @param font_name filename where the font file is located 84 * @return a pointer to the font or NULL in case of error 85 */ 86 lv_font_t * lv_font_load(const char * font_name) 87 { 88 lv_fs_file_t file; 89 lv_fs_res_t res = lv_fs_open(&file, font_name, LV_FS_MODE_RD); 90 if(res != LV_FS_RES_OK) 91 return NULL; 92 93 lv_font_t * font = lv_mem_alloc(sizeof(lv_font_t)); 94 if(font) { 95 memset(font, 0, sizeof(lv_font_t)); 96 if(!lvgl_load_font(&file, font)) { 97 LV_LOG_WARN("Error loading font file: %s\n", font_name); 98 /* 99 * When `lvgl_load_font` fails it can leak some pointers. 100 * All non-null pointers can be assumed as allocated and 101 * `lv_font_free` should free them correctly. 102 */ 103 lv_font_free(font); 104 font = NULL; 105 } 106 } 107 108 lv_fs_close(&file); 109 110 return font; 111 } 112 113 /** 114 * Frees the memory allocated by the `lv_font_load()` function 115 * @param font lv_font_t object created by the lv_font_load function 116 */ 117 void lv_font_free(lv_font_t * font) 118 { 119 if(NULL != font) { 120 lv_font_fmt_txt_dsc_t * dsc = (lv_font_fmt_txt_dsc_t *)font->dsc; 121 122 if(NULL != dsc) { 123 124 if(dsc->kern_classes == 0) { 125 lv_font_fmt_txt_kern_pair_t * kern_dsc = 126 (lv_font_fmt_txt_kern_pair_t *)dsc->kern_dsc; 127 128 if(NULL != kern_dsc) { 129 if(kern_dsc->glyph_ids) 130 lv_mem_free((void *)kern_dsc->glyph_ids); 131 132 if(kern_dsc->values) 133 lv_mem_free((void *)kern_dsc->values); 134 135 lv_mem_free((void *)kern_dsc); 136 } 137 } 138 else { 139 lv_font_fmt_txt_kern_classes_t * kern_dsc = 140 (lv_font_fmt_txt_kern_classes_t *)dsc->kern_dsc; 141 142 if(NULL != kern_dsc) { 143 if(kern_dsc->class_pair_values) 144 lv_mem_free((void *)kern_dsc->class_pair_values); 145 146 if(kern_dsc->left_class_mapping) 147 lv_mem_free((void *)kern_dsc->left_class_mapping); 148 149 if(kern_dsc->right_class_mapping) 150 lv_mem_free((void *)kern_dsc->right_class_mapping); 151 152 lv_mem_free((void *)kern_dsc); 153 } 154 } 155 156 lv_font_fmt_txt_cmap_t * cmaps = 157 (lv_font_fmt_txt_cmap_t *)dsc->cmaps; 158 159 if(NULL != cmaps) { 160 for(int i = 0; i < dsc->cmap_num; ++i) { 161 if(NULL != cmaps[i].glyph_id_ofs_list) 162 lv_mem_free((void *)cmaps[i].glyph_id_ofs_list); 163 if(NULL != cmaps[i].unicode_list) 164 lv_mem_free((void *)cmaps[i].unicode_list); 165 } 166 lv_mem_free(cmaps); 167 } 168 169 if(NULL != dsc->glyph_bitmap) { 170 lv_mem_free((void *)dsc->glyph_bitmap); 171 } 172 if(NULL != dsc->glyph_dsc) { 173 lv_mem_free((void *)dsc->glyph_dsc); 174 } 175 lv_mem_free(dsc); 176 } 177 lv_mem_free(font); 178 } 179 } 180 181 /********************** 182 * STATIC FUNCTIONS 183 **********************/ 184 185 static bit_iterator_t init_bit_iterator(lv_fs_file_t * fp) 186 { 187 bit_iterator_t it; 188 it.fp = fp; 189 it.bit_pos = -1; 190 it.byte_value = 0; 191 return it; 192 } 193 194 static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res) 195 { 196 unsigned int value = 0; 197 while(n_bits--) { 198 it->byte_value = it->byte_value << 1; 199 it->bit_pos--; 200 201 if(it->bit_pos < 0) { 202 it->bit_pos = 7; 203 *res = lv_fs_read(it->fp, &(it->byte_value), 1, NULL); 204 if(*res != LV_FS_RES_OK) { 205 return 0; 206 } 207 } 208 int8_t bit = (it->byte_value & 0x80) ? 1 : 0; 209 210 value |= (bit << n_bits); 211 } 212 *res = LV_FS_RES_OK; 213 return value; 214 } 215 216 static int read_bits_signed(bit_iterator_t * it, int n_bits, lv_fs_res_t * res) 217 { 218 unsigned int value = read_bits(it, n_bits, res); 219 if(value & (1 << (n_bits - 1))) { 220 value |= ~0u << n_bits; 221 } 222 return value; 223 } 224 225 static int read_label(lv_fs_file_t * fp, int start, const char * label) 226 { 227 lv_fs_seek(fp, start, LV_FS_SEEK_SET); 228 229 uint32_t length; 230 char buf[4]; 231 232 if(lv_fs_read(fp, &length, 4, NULL) != LV_FS_RES_OK 233 || lv_fs_read(fp, buf, 4, NULL) != LV_FS_RES_OK 234 || memcmp(label, buf, 4) != 0) { 235 LV_LOG_WARN("Error reading '%s' label.", label); 236 return -1; 237 } 238 239 return length; 240 } 241 242 static bool load_cmaps_tables(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, 243 uint32_t cmaps_start, cmap_table_bin_t * cmap_table) 244 { 245 if(lv_fs_read(fp, cmap_table, font_dsc->cmap_num * sizeof(cmap_table_bin_t), NULL) != LV_FS_RES_OK) { 246 return false; 247 } 248 249 for(unsigned int i = 0; i < font_dsc->cmap_num; ++i) { 250 lv_fs_res_t res = lv_fs_seek(fp, cmaps_start + cmap_table[i].data_offset, LV_FS_SEEK_SET); 251 if(res != LV_FS_RES_OK) { 252 return false; 253 } 254 255 lv_font_fmt_txt_cmap_t * cmap = (lv_font_fmt_txt_cmap_t *) & (font_dsc->cmaps[i]); 256 257 cmap->range_start = cmap_table[i].range_start; 258 cmap->range_length = cmap_table[i].range_length; 259 cmap->glyph_id_start = cmap_table[i].glyph_id_start; 260 cmap->type = cmap_table[i].format_type; 261 262 switch(cmap_table[i].format_type) { 263 case LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL: { 264 uint8_t ids_size = sizeof(uint8_t) * cmap_table[i].data_entries_count; 265 uint8_t * glyph_id_ofs_list = lv_mem_alloc(ids_size); 266 267 cmap->glyph_id_ofs_list = glyph_id_ofs_list; 268 269 if(lv_fs_read(fp, glyph_id_ofs_list, ids_size, NULL) != LV_FS_RES_OK) { 270 return false; 271 } 272 273 cmap->list_length = cmap->range_length; 274 break; 275 } 276 case LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY: 277 break; 278 case LV_FONT_FMT_TXT_CMAP_SPARSE_FULL: 279 case LV_FONT_FMT_TXT_CMAP_SPARSE_TINY: { 280 uint32_t list_size = sizeof(uint16_t) * cmap_table[i].data_entries_count; 281 uint16_t * unicode_list = (uint16_t *)lv_mem_alloc(list_size); 282 283 cmap->unicode_list = unicode_list; 284 cmap->list_length = cmap_table[i].data_entries_count; 285 286 if(lv_fs_read(fp, unicode_list, list_size, NULL) != LV_FS_RES_OK) { 287 return false; 288 } 289 290 if(cmap_table[i].format_type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) { 291 uint16_t * buf = lv_mem_alloc(sizeof(uint16_t) * cmap->list_length); 292 293 cmap->glyph_id_ofs_list = buf; 294 295 if(lv_fs_read(fp, buf, sizeof(uint16_t) * cmap->list_length, NULL) != LV_FS_RES_OK) { 296 return false; 297 } 298 } 299 break; 300 } 301 default: 302 LV_LOG_WARN("Unknown cmaps format type %d.", cmap_table[i].format_type); 303 return false; 304 } 305 } 306 return true; 307 } 308 309 static int32_t load_cmaps(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint32_t cmaps_start) 310 { 311 int32_t cmaps_length = read_label(fp, cmaps_start, "cmap"); 312 if(cmaps_length < 0) { 313 return -1; 314 } 315 316 uint32_t cmaps_subtables_count; 317 if(lv_fs_read(fp, &cmaps_subtables_count, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { 318 return -1; 319 } 320 321 lv_font_fmt_txt_cmap_t * cmaps = 322 lv_mem_alloc(cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); 323 324 memset(cmaps, 0, cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); 325 326 font_dsc->cmaps = cmaps; 327 font_dsc->cmap_num = cmaps_subtables_count; 328 329 cmap_table_bin_t * cmaps_tables = lv_mem_alloc(sizeof(cmap_table_bin_t) * font_dsc->cmap_num); 330 331 bool success = load_cmaps_tables(fp, font_dsc, cmaps_start, cmaps_tables); 332 333 lv_mem_free(cmaps_tables); 334 335 return success ? cmaps_length : -1; 336 } 337 338 static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, 339 uint32_t start, uint32_t * glyph_offset, uint32_t loca_count, font_header_bin_t * header) 340 { 341 int32_t glyph_length = read_label(fp, start, "glyf"); 342 if(glyph_length < 0) { 343 return -1; 344 } 345 346 lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = (lv_font_fmt_txt_glyph_dsc_t *) 347 lv_mem_alloc(loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); 348 349 memset(glyph_dsc, 0, loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); 350 351 font_dsc->glyph_dsc = glyph_dsc; 352 353 int cur_bmp_size = 0; 354 355 for(unsigned int i = 0; i < loca_count; ++i) { 356 lv_font_fmt_txt_glyph_dsc_t * gdsc = &glyph_dsc[i]; 357 358 lv_fs_res_t res = lv_fs_seek(fp, start + glyph_offset[i], LV_FS_SEEK_SET); 359 if(res != LV_FS_RES_OK) { 360 return -1; 361 } 362 363 bit_iterator_t bit_it = init_bit_iterator(fp); 364 365 if(header->advance_width_bits == 0) { 366 gdsc->adv_w = header->default_advance_width; 367 } 368 else { 369 gdsc->adv_w = read_bits(&bit_it, header->advance_width_bits, &res); 370 if(res != LV_FS_RES_OK) { 371 return -1; 372 } 373 } 374 375 if(header->advance_width_format == 0) { 376 gdsc->adv_w *= 16; 377 } 378 379 gdsc->ofs_x = read_bits_signed(&bit_it, header->xy_bits, &res); 380 if(res != LV_FS_RES_OK) { 381 return -1; 382 } 383 384 gdsc->ofs_y = read_bits_signed(&bit_it, header->xy_bits, &res); 385 if(res != LV_FS_RES_OK) { 386 return -1; 387 } 388 389 gdsc->box_w = read_bits(&bit_it, header->wh_bits, &res); 390 if(res != LV_FS_RES_OK) { 391 return -1; 392 } 393 394 gdsc->box_h = read_bits(&bit_it, header->wh_bits, &res); 395 if(res != LV_FS_RES_OK) { 396 return -1; 397 } 398 399 int nbits = header->advance_width_bits + 2 * header->xy_bits + 2 * header->wh_bits; 400 int next_offset = (i < loca_count - 1) ? glyph_offset[i + 1] : (uint32_t)glyph_length; 401 int bmp_size = next_offset - glyph_offset[i] - nbits / 8; 402 403 if(i == 0) { 404 gdsc->adv_w = 0; 405 gdsc->box_w = 0; 406 gdsc->box_h = 0; 407 gdsc->ofs_x = 0; 408 gdsc->ofs_y = 0; 409 } 410 411 gdsc->bitmap_index = cur_bmp_size; 412 if(gdsc->box_w * gdsc->box_h != 0) { 413 cur_bmp_size += bmp_size; 414 } 415 } 416 417 uint8_t * glyph_bmp = (uint8_t *)lv_mem_alloc(sizeof(uint8_t) * cur_bmp_size); 418 419 font_dsc->glyph_bitmap = glyph_bmp; 420 421 cur_bmp_size = 0; 422 423 for(unsigned int i = 1; i < loca_count; ++i) { 424 lv_fs_res_t res = lv_fs_seek(fp, start + glyph_offset[i], LV_FS_SEEK_SET); 425 if(res != LV_FS_RES_OK) { 426 return -1; 427 } 428 bit_iterator_t bit_it = init_bit_iterator(fp); 429 430 int nbits = header->advance_width_bits + 2 * header->xy_bits + 2 * header->wh_bits; 431 432 read_bits(&bit_it, nbits, &res); 433 if(res != LV_FS_RES_OK) { 434 return -1; 435 } 436 437 if(glyph_dsc[i].box_w * glyph_dsc[i].box_h == 0) { 438 continue; 439 } 440 441 int next_offset = (i < loca_count - 1) ? glyph_offset[i + 1] : (uint32_t)glyph_length; 442 int bmp_size = next_offset - glyph_offset[i] - nbits / 8; 443 444 if(nbits % 8 == 0) { /*Fast path*/ 445 if(lv_fs_read(fp, &glyph_bmp[cur_bmp_size], bmp_size, NULL) != LV_FS_RES_OK) { 446 return -1; 447 } 448 } 449 else { 450 for(int k = 0; k < bmp_size - 1; ++k) { 451 glyph_bmp[cur_bmp_size + k] = read_bits(&bit_it, 8, &res); 452 if(res != LV_FS_RES_OK) { 453 return -1; 454 } 455 } 456 glyph_bmp[cur_bmp_size + bmp_size - 1] = read_bits(&bit_it, 8 - nbits % 8, &res); 457 if(res != LV_FS_RES_OK) { 458 return -1; 459 } 460 461 /*The last fragment should be on the MSB but read_bits() will place it to the LSB*/ 462 glyph_bmp[cur_bmp_size + bmp_size - 1] = glyph_bmp[cur_bmp_size + bmp_size - 1] << (nbits % 8); 463 464 } 465 466 cur_bmp_size += bmp_size; 467 } 468 return glyph_length; 469 } 470 471 /* 472 * Loads a `lv_font_t` from a binary file, given a `lv_fs_file_t`. 473 * 474 * Memory allocations on `lvgl_load_font` should be immediately zeroed and 475 * the pointer should be set on the `lv_font_t` data before any possible return. 476 * 477 * When something fails, it returns `false` and the memory on the `lv_font_t` 478 * still needs to be freed using `lv_font_free`. 479 * 480 * `lv_font_free` will assume that all non-null pointers are allocated and 481 * should be freed. 482 */ 483 static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) 484 { 485 lv_font_fmt_txt_dsc_t * font_dsc = (lv_font_fmt_txt_dsc_t *) 486 lv_mem_alloc(sizeof(lv_font_fmt_txt_dsc_t)); 487 488 memset(font_dsc, 0, sizeof(lv_font_fmt_txt_dsc_t)); 489 490 font->dsc = font_dsc; 491 492 /*header*/ 493 int32_t header_length = read_label(fp, 0, "head"); 494 if(header_length < 0) { 495 return false; 496 } 497 498 font_header_bin_t font_header; 499 if(lv_fs_read(fp, &font_header, sizeof(font_header_bin_t), NULL) != LV_FS_RES_OK) { 500 return false; 501 } 502 503 font->base_line = -font_header.descent; 504 font->line_height = font_header.ascent - font_header.descent; 505 font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt; 506 font->get_glyph_bitmap = lv_font_get_bitmap_fmt_txt; 507 font->subpx = font_header.subpixels_mode; 508 font->underline_position = font_header.underline_position; 509 font->underline_thickness = font_header.underline_thickness; 510 511 font_dsc->bpp = font_header.bits_per_pixel; 512 font_dsc->kern_scale = font_header.kerning_scale; 513 font_dsc->bitmap_format = font_header.compression_id; 514 515 /*cmaps*/ 516 uint32_t cmaps_start = header_length; 517 int32_t cmaps_length = load_cmaps(fp, font_dsc, cmaps_start); 518 if(cmaps_length < 0) { 519 return false; 520 } 521 522 /*loca*/ 523 uint32_t loca_start = cmaps_start + cmaps_length; 524 int32_t loca_length = read_label(fp, loca_start, "loca"); 525 if(loca_length < 0) { 526 return false; 527 } 528 529 uint32_t loca_count; 530 if(lv_fs_read(fp, &loca_count, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { 531 return false; 532 } 533 534 bool failed = false; 535 uint32_t * glyph_offset = lv_mem_alloc(sizeof(uint32_t) * (loca_count + 1)); 536 537 if(font_header.index_to_loc_format == 0) { 538 for(unsigned int i = 0; i < loca_count; ++i) { 539 uint16_t offset; 540 if(lv_fs_read(fp, &offset, sizeof(uint16_t), NULL) != LV_FS_RES_OK) { 541 failed = true; 542 break; 543 } 544 glyph_offset[i] = offset; 545 } 546 } 547 else if(font_header.index_to_loc_format == 1) { 548 if(lv_fs_read(fp, glyph_offset, loca_count * sizeof(uint32_t), NULL) != LV_FS_RES_OK) { 549 failed = true; 550 } 551 } 552 else { 553 LV_LOG_WARN("Unknown index_to_loc_format: %d.", font_header.index_to_loc_format); 554 failed = true; 555 } 556 557 if(failed) { 558 lv_mem_free(glyph_offset); 559 return false; 560 } 561 562 /*glyph*/ 563 uint32_t glyph_start = loca_start + loca_length; 564 int32_t glyph_length = load_glyph( 565 fp, font_dsc, glyph_start, glyph_offset, loca_count, &font_header); 566 567 lv_mem_free(glyph_offset); 568 569 if(glyph_length < 0) { 570 return false; 571 } 572 573 if(font_header.tables_count < 4) { 574 font_dsc->kern_dsc = NULL; 575 font_dsc->kern_classes = 0; 576 font_dsc->kern_scale = 0; 577 return true; 578 } 579 580 uint32_t kern_start = glyph_start + glyph_length; 581 582 int32_t kern_length = load_kern(fp, font_dsc, font_header.glyph_id_format, kern_start); 583 584 return kern_length >= 0; 585 } 586 587 int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t format, uint32_t start) 588 { 589 int32_t kern_length = read_label(fp, start, "kern"); 590 if(kern_length < 0) { 591 return -1; 592 } 593 594 uint8_t kern_format_type; 595 int32_t padding; 596 if(lv_fs_read(fp, &kern_format_type, sizeof(uint8_t), NULL) != LV_FS_RES_OK || 597 lv_fs_read(fp, &padding, 3 * sizeof(uint8_t), NULL) != LV_FS_RES_OK) { 598 return -1; 599 } 600 601 if(0 == kern_format_type) { /*sorted pairs*/ 602 lv_font_fmt_txt_kern_pair_t * kern_pair = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_pair_t)); 603 604 memset(kern_pair, 0, sizeof(lv_font_fmt_txt_kern_pair_t)); 605 606 font_dsc->kern_dsc = kern_pair; 607 font_dsc->kern_classes = 0; 608 609 uint32_t glyph_entries; 610 if(lv_fs_read(fp, &glyph_entries, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { 611 return -1; 612 } 613 614 int ids_size; 615 if(format == 0) { 616 ids_size = sizeof(int8_t) * 2 * glyph_entries; 617 } 618 else { 619 ids_size = sizeof(int16_t) * 2 * glyph_entries; 620 } 621 622 uint8_t * glyph_ids = lv_mem_alloc(ids_size); 623 int8_t * values = lv_mem_alloc(glyph_entries); 624 625 kern_pair->glyph_ids_size = format; 626 kern_pair->pair_cnt = glyph_entries; 627 kern_pair->glyph_ids = glyph_ids; 628 kern_pair->values = values; 629 630 if(lv_fs_read(fp, glyph_ids, ids_size, NULL) != LV_FS_RES_OK) { 631 return -1; 632 } 633 634 if(lv_fs_read(fp, values, glyph_entries, NULL) != LV_FS_RES_OK) { 635 return -1; 636 } 637 } 638 else if(3 == kern_format_type) { /*array M*N of classes*/ 639 640 lv_font_fmt_txt_kern_classes_t * kern_classes = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_classes_t)); 641 642 memset(kern_classes, 0, sizeof(lv_font_fmt_txt_kern_classes_t)); 643 644 font_dsc->kern_dsc = kern_classes; 645 font_dsc->kern_classes = 1; 646 647 uint16_t kern_class_mapping_length; 648 uint8_t kern_table_rows; 649 uint8_t kern_table_cols; 650 651 if(lv_fs_read(fp, &kern_class_mapping_length, sizeof(uint16_t), NULL) != LV_FS_RES_OK || 652 lv_fs_read(fp, &kern_table_rows, sizeof(uint8_t), NULL) != LV_FS_RES_OK || 653 lv_fs_read(fp, &kern_table_cols, sizeof(uint8_t), NULL) != LV_FS_RES_OK) { 654 return -1; 655 } 656 657 int kern_values_length = sizeof(int8_t) * kern_table_rows * kern_table_cols; 658 659 uint8_t * kern_left = lv_mem_alloc(kern_class_mapping_length); 660 uint8_t * kern_right = lv_mem_alloc(kern_class_mapping_length); 661 int8_t * kern_values = lv_mem_alloc(kern_values_length); 662 663 kern_classes->left_class_mapping = kern_left; 664 kern_classes->right_class_mapping = kern_right; 665 kern_classes->left_class_cnt = kern_table_rows; 666 kern_classes->right_class_cnt = kern_table_cols; 667 kern_classes->class_pair_values = kern_values; 668 669 if(lv_fs_read(fp, kern_left, kern_class_mapping_length, NULL) != LV_FS_RES_OK || 670 lv_fs_read(fp, kern_right, kern_class_mapping_length, NULL) != LV_FS_RES_OK || 671 lv_fs_read(fp, kern_values, kern_values_length, NULL) != LV_FS_RES_OK) { 672 return -1; 673 } 674 } 675 else { 676 LV_LOG_WARN("Unknown kern_format_type: %d", kern_format_type); 677 return -1; 678 } 679 680 return kern_length; 681 }