vft_draw.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /****************************************************************************
  2. *
  3. * The MIT License (MIT)
  4. *
  5. * Copyright 2020 NXP
  6. * All Rights Reserved.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining
  9. * a copy of this software and associated documentation files (the
  10. * 'Software'), to deal in the Software without restriction, including
  11. * without limitation the rights to use, copy, modify, merge, publish,
  12. * distribute, sub license, and/or sell copies of the Software, and to
  13. * permit persons to whom the Software is furnished to do so, subject
  14. * to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice (including the
  17. * next paragraph) shall be included in all copies or substantial
  18. * portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
  21. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  23. * IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
  24. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  25. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  26. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. *
  28. *****************************************************************************/
  29. /** Include Files */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include "vg_lite.h"
  34. #include "vg_lite_text.h"
  35. #include "vft_draw.h"
  36. #include "vft_debug.h"
  37. #include "rtthread.h"
  38. /** Macros */
  39. #define VFT_ALLOC(x) _mem_allocate(x)
  40. #define VFT_FREE(x) _mem_free(x)
  41. #define READ_BIN_FIELD(x) memcpy(&g->x, (buf + offset), sizeof(g->x)); offset += sizeof(g->x)
  42. #define READ_BIN_FIELD_STR(x) READ_BIN_FIELD(x)
  43. #define READ_BIN_FIELD_UINT16(x) READ_BIN_FIELD(x)
  44. #define READ_BIN_FIELD_UINT32(x) READ_BIN_FIELD(x)
  45. #define READ_BIN_FIELD_FLOAT(x) READ_BIN_FIELD(x)
  46. #define READ_BIN_FIELD_DUMMY_POINTER(x) offset += 4;
  47. #define GLYPH_CACHE_SIZE 16
  48. #define ENABLE_TEXT_WRAP 0
  49. #define HALT_ALLOCATOR_ERROR 1
  50. /** Data structures */
  51. typedef struct glyph_cache_desc {
  52. vg_lite_path_t *h_path;
  53. glyph_desc_t *g;
  54. uint32_t use_count;
  55. }glyph_cache_desc_t;
  56. /** Internal or external API prototypes */
  57. /** Globals */
  58. static int g_glyph_cache_init_done = 0;
  59. static glyph_cache_desc_t g_glyph_cache[GLYPH_CACHE_SIZE];
  60. int g_total_bytes = 0;
  61. /** Externs if any */
  62. /* Internal API, not published to user */
  63. font_face_desc_t *_vg_lite_get_vector_font(vg_lite_font_t font_idx);
  64. void matrix_multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t *mult);
  65. void *_mem_allocate(int size)
  66. {
  67. char *buf = NULL;
  68. if ( size == 0 ) {
  69. printf("ERROR: HALT: Why allocating %d bytes\n", size);
  70. #if HALT_ALLOCATOR_ERROR
  71. while(1);
  72. #else
  73. return NULL;
  74. #endif
  75. }
  76. buf = rt_malloc(size);
  77. if (buf == NULL) {
  78. printf("ERROR: HALT: allocating %d bytes \"system out of memory\"\n", size);
  79. #if HALT_ALLOCATOR_ERROR
  80. while(1);
  81. #else
  82. return NULL;
  83. #endif
  84. }
  85. g_total_bytes += size;
  86. return buf;
  87. }
  88. void _mem_free(void *buf)
  89. {
  90. rt_free(buf);
  91. }
  92. /** GLYPH CACHING Code */
  93. void glyph_cache_init(void)
  94. {
  95. if ( g_glyph_cache_init_done == 0 ) {
  96. memset(g_glyph_cache,0,sizeof(g_glyph_cache));
  97. g_glyph_cache_init_done = 1;
  98. }
  99. }
  100. void glyph_cache_free(void)
  101. {
  102. int i;
  103. for (i=0; i<GLYPH_CACHE_SIZE; i++) {
  104. if ( g_glyph_cache[i].h_path != NULL ) {
  105. /* For non-mapped path this resetting is sufficient */
  106. vg_lite_clear_path(g_glyph_cache[i].h_path);
  107. /* Release path handle */
  108. VFT_FREE(g_glyph_cache[i].h_path);
  109. /* Reset pointer */
  110. g_glyph_cache[i].h_path = NULL;
  111. }
  112. }
  113. /* Next time font init will be required */
  114. g_glyph_cache_init_done = 0;
  115. }
  116. vg_lite_path_t *vft_cache_lookup(glyph_desc_t *g)
  117. {
  118. int i;
  119. int unused_idx = 0;
  120. /* Not present caching code does not handle multiple font-face */
  121. glyph_cache_init();
  122. /* Check if path object for given glyph exists */
  123. for (i=0; i<GLYPH_CACHE_SIZE; i++) {
  124. if ( g_glyph_cache[i].g != NULL && g->unicode ==
  125. g_glyph_cache[i].g->unicode )
  126. {
  127. g_glyph_cache[i].use_count++;
  128. return g_glyph_cache[i].h_path;
  129. }
  130. }
  131. /* Find least used descriptor */
  132. unused_idx = 0;
  133. for (i=1; i<GLYPH_CACHE_SIZE; i++) {
  134. if ( g_glyph_cache[i].use_count <
  135. g_glyph_cache[unused_idx].use_count ) {
  136. unused_idx = i;
  137. }
  138. }
  139. /* Re-cycle descriptor */
  140. if ( g_glyph_cache[unused_idx].h_path != NULL ) {
  141. /* For non-mapped path this resetting is sufficient */
  142. vg_lite_clear_path(g_glyph_cache[unused_idx].h_path);
  143. } else {
  144. /* Allocate new path object */
  145. g_glyph_cache[unused_idx].h_path =
  146. (vg_lite_path_t *)VFT_ALLOC(sizeof(vg_lite_path_t));
  147. }
  148. /* Allocate new path */
  149. vg_lite_init_path(g_glyph_cache[unused_idx].h_path,
  150. VG_LITE_FP32, VG_LITE_HIGH,
  151. g->path.num_draw_cmds*4,
  152. g->path.draw_cmds,
  153. g->path.bounds[0],
  154. g->path.bounds[1],
  155. g->path.bounds[2],
  156. g->path.bounds[3]);
  157. g_glyph_cache[unused_idx].g = g;
  158. g_glyph_cache[unused_idx].use_count = 1;
  159. return g_glyph_cache[unused_idx].h_path;
  160. }
  161. /** Render text using vector fonts */
  162. int vg_lite_vtf_draw_text(vg_lite_buffer_t *rt, int x, int y,
  163. vg_lite_blend_t blend,
  164. vg_lite_font_t font,
  165. vg_lite_matrix_t *matrix,
  166. vg_lite_font_attributes_t * attributes,
  167. char *text)
  168. {
  169. font_face_desc_t *font_face;
  170. glyph_desc_t* g1 = NULL;
  171. glyph_desc_t* g2;
  172. int error = 0;
  173. float font_scale = 1.0;
  174. int text_wrap = 0;
  175. font_face = (font_face_desc_t *)_vg_lite_get_vector_font(font);
  176. attributes->last_dx = 0;
  177. font_scale = ((1.0*attributes->font_height)/font_face->units_per_em);
  178. vg_lite_matrix_t mat;
  179. vg_lite_fill_t fill_rule = VG_LITE_FILL_NON_ZERO;
  180. vg_lite_color_t color = attributes->text_color;
  181. /* Compute size of tex in pixels
  182. * For center alignment adjust x position
  183. * Present parser has bug in encoding alignment value,
  184. * Once it is fixed following code will align text in center
  185. */
  186. if ( attributes->alignment == eTextAlignCenter ||
  187. attributes->alignment == eTextAlignRight ) {
  188. char *t2 = text;
  189. int dx = 0;
  190. uint16_t ug2; /* Unicode glyph */
  191. int kx;
  192. /* Case of center alignement */
  193. while (*t2 != '\0') {
  194. ug2 = *t2;
  195. kx = 0;
  196. g2 = vft_find_glyph(font_face, ug2);
  197. if (g1 != NULL && g2 != NULL) {
  198. kx = vft_glyph_distance(g1, g2);
  199. }
  200. dx += ((g2->horiz_adv_x + kx )* font_scale);
  201. t2++;
  202. }
  203. if ( attributes->alignment == eTextAlignCenter) {
  204. x -= (dx/2);
  205. } else if ( attributes->alignment == eTextAlignRight) {
  206. x -= (dx);
  207. }
  208. }
  209. /* Compute pixels that will cover this vector path */
  210. while (*text != '\0') {
  211. uint16_t ug2; /* Unicode glyph */
  212. int kx;
  213. if (text_wrap == 0) {
  214. vg_lite_identity(&mat);
  215. matrix_multiply(&mat, matrix);
  216. vg_lite_translate(x,y, &mat);
  217. vg_lite_scale(font_scale,font_scale, &mat); // 0.35 = height/units_per_em
  218. vg_lite_scale(-1.0,1.0, &mat);
  219. vg_lite_scale(-1.0,-1.0, &mat);
  220. text_wrap = 1;
  221. }
  222. /* Read unicode character */
  223. kx = 0;
  224. ug2 = *text;
  225. g2 = vft_find_glyph(font_face, ug2);
  226. if (g1 != NULL && g2 != NULL) {
  227. kx = vft_glyph_distance(g1, g2);
  228. }
  229. #if (ENABLE_TEXT_WRAP==1)
  230. /* Wrap text */
  231. if ( (x + attributes->last_dx + ((g2->horiz_adv_x + kx )* font_scale))
  232. >= (720 - 5) )
  233. {
  234. text_wrap = 0;
  235. attributes->last_dx = 0;
  236. y += (attributes->font_height + 1);
  237. continue;
  238. }
  239. #endif /* ENABLE_TEXT_WRAP */
  240. /* Compute glyph size in horizontal dimension */
  241. g1 = g2;
  242. text++;
  243. error = vg_lite_draw(rt, vft_cache_lookup(g2),
  244. fill_rule,
  245. &mat,
  246. blend,
  247. color);
  248. if ( error != VG_LITE_SUCCESS ) {
  249. break;
  250. }
  251. vg_lite_translate(g2->horiz_adv_x + kx, 0, &mat);
  252. attributes->last_dx += ((g2->horiz_adv_x + kx )* font_scale);
  253. }
  254. attributes->last_dx += 2; /* Space between 2 text strings */
  255. return 0;
  256. }
  257. void load_font_face(font_face_desc_t* font_face, uint8_t* buf, int font_face_offset)
  258. {
  259. font_face_desc_t* g = font_face;
  260. int offset = font_face_offset;
  261. READ_BIN_FIELD_STR(font_family_name);
  262. READ_BIN_FIELD_UINT16(units_per_em);
  263. READ_BIN_FIELD_UINT16(ascent);
  264. READ_BIN_FIELD_UINT16(descent);
  265. READ_BIN_FIELD_UINT16(vg_font);
  266. READ_BIN_FIELD_UINT32(num_glyphs);
  267. }
  268. void load_glyph_table(font_face_desc_t* font_face, uint8_t* buf, int glyph_table_offset)
  269. {
  270. int offset = glyph_table_offset;
  271. for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
  272. glyph_desc_t* g = &font_face->glyphs[i];
  273. memset(g, 0, sizeof(glyph_desc_t));
  274. READ_BIN_FIELD_UINT16(unicode);
  275. READ_BIN_FIELD_UINT16(horiz_adv_x);
  276. READ_BIN_FIELD_UINT32(kern_num_entries);
  277. READ_BIN_FIELD_UINT32(kern_table_offset);
  278. READ_BIN_FIELD_DUMMY_POINTER();
  279. READ_BIN_FIELD_FLOAT(path.bounds[0]);
  280. READ_BIN_FIELD_FLOAT(path.bounds[1]);
  281. READ_BIN_FIELD_FLOAT(path.bounds[2]);
  282. READ_BIN_FIELD_FLOAT(path.bounds[3]);
  283. READ_BIN_FIELD_UINT32(path.num_draw_cmds);
  284. READ_BIN_FIELD_UINT32(path.draw_cmds_offset);
  285. READ_BIN_FIELD_DUMMY_POINTER();
  286. font_face->glyphs[i].kern_table = (kern_desc_t *)(buf + font_face->glyphs[i].kern_table_offset);
  287. font_face->glyphs[i].path.draw_cmds = (float *)(buf + font_face->glyphs[i].path.draw_cmds_offset);
  288. TRACE_INFO(("Glyph: '%c'\n", g->unicode));
  289. vft_dbg_glyph_desc(g, d_offset);
  290. }
  291. }
  292. /* Load vector font ROM table from file */
  293. font_face_desc_t* vft_load_from_buffer(char* buf_base, int file_size)
  294. {
  295. font_face_desc_t* font_face = NULL;
  296. uint32_t* blk_hdr;
  297. //int error = 0;
  298. /* Setup internal memory pointers of font_face_desc_t */
  299. int font_face_offset = 0;
  300. int glyph_table_offset = 0;
  301. //int kern_table_offset = 0;
  302. //int path_data_offset = 0;
  303. int offset = 0;
  304. /* May be we can avoid this lookup */
  305. while (offset < file_size) {
  306. blk_hdr = (uint32_t*)(buf_base + offset);
  307. eFontBlock_t eType = (eFontBlock_t)((*blk_hdr) >> 24);
  308. int size = ((*blk_hdr) & ((1<<24)-1));
  309. TRACE_BIN(("BIN: %08x: block(%hu, %hu)\n",
  310. offset, eType, size));
  311. offset += BLK_HDR_SIZE;
  312. /* Check integrity of block and then only proceed */
  313. switch (eType) {
  314. case eFontFaceDesc:
  315. font_face_offset = offset;
  316. break;
  317. case eGlyphTableDesc:
  318. glyph_table_offset = offset;
  319. break;
  320. case eKernTableDesc:
  321. //kern_table_offset = offset;
  322. break;
  323. case eGlyphData:
  324. //path_data_offset = offset;
  325. break;
  326. default:
  327. case eUnkBlock:
  328. case eMaxBlock:
  329. return NULL;;
  330. }
  331. offset += size;
  332. }
  333. if (offset < 0 || offset > file_size) {
  334. printf("ERROR: Vector font file integrity error aborting..\n");
  335. return NULL;
  336. }
  337. /* Make structure binary compliant to reduce loading time */
  338. font_face = (font_face_desc_t*)(buf_base + font_face_offset);
  339. font_face->glyphs = (glyph_desc_t*)(buf_base + glyph_table_offset);
  340. VFT_DBG_FONT_FACE_DESC(font_face, font_face_offset);
  341. for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
  342. /* Update internal pointer from memory mapped file */
  343. font_face->glyphs[i].kern_table =
  344. (kern_desc_t*)(buf_base + font_face->glyphs[i].kern_table_offset);
  345. font_face->glyphs[i].path.draw_cmds =
  346. (float*)(buf_base +
  347. font_face->glyphs[i].path.draw_cmds_offset);
  348. /* Try to get these paramters from Binary object or attributes */
  349. //vg_lite_format_t data_format = VG_LITE_FP32; //VG_LITE_S16;
  350. //vg_lite_quality_t quality = VG_LITE_HIGH;
  351. }
  352. VFT_DBG_GLYPH_TABLE(font_face, glyph_table_offset);
  353. VFT_DBG_KERN_TABLE(font_face, kern_table_offset);
  354. VFT_DBG_PATH_TABLE(font_face, path_data_offset);
  355. return font_face;
  356. }
  357. /* Find glyph of given character from glyph table */
  358. glyph_desc_t* vft_find_glyph(font_face_desc_t* font_face, uint16_t ug2)
  359. {
  360. const int num_glyphs = font_face->num_glyphs;
  361. glyph_desc_t* glyphs = font_face->glyphs;
  362. /*
  363. * Present approach is slow linear search, this is ok in 1st prototype
  364. * Since glyph table is already sorted, we can have binary search
  365. */
  366. for (int i = 0; i < num_glyphs; i++) {
  367. if (glyphs[i].unicode == ug2) {
  368. return (glyph_desc_t*)&glyphs[i];
  369. }
  370. }
  371. return (glyph_desc_t*)&glyphs[0];;
  372. }
  373. /* Find distance between 2 glyph symbols */
  374. int vft_glyph_distance(glyph_desc_t* g1, glyph_desc_t* g2)
  375. {
  376. signed short kx = 0;
  377. uint16_t ug2 = g2->unicode;
  378. kern_desc_t* kern_table = &g1->kern_table[0];
  379. for (int i = 0; i < g1->kern_num_entries; i++) {
  380. if (kern_table[i].unicode == ug2) {
  381. signed short *pkx = (signed short *)&kern_table[i].kern;
  382. kx = *pkx;
  383. break;
  384. }
  385. }
  386. return kx;
  387. }
  388. /*
  389. * Get internal vector path of given glyph
  390. * This is internal function
  391. */
  392. path_desc_t* vft_get_glyph_path(glyph_desc_t* g2)
  393. {
  394. return &g2->path;
  395. }
  396. /* Unload font face descriptor and all glyphs */
  397. void vft_unload(font_face_desc_t* font_face)
  398. {
  399. glyph_cache_free();
  400. //VFT_FREE(font_face);
  401. }