font_hz_file.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Cached HZ font engine
  3. */
  4. #include <rtgui/dc.h>
  5. #include <rtgui/font.h>
  6. #include <rtgui/tree.h>
  7. #include <rtgui/rtgui_system.h>
  8. #ifdef RTGUI_USING_HZ_FILE
  9. #include <dfs_posix.h>
  10. #define HZ_CACHE_MAX 64
  11. static int _font_cache_compare(struct hz_cache* node1, struct hz_cache* node2);
  12. static void rtgui_hz_file_font_load(struct rtgui_font* font);
  13. static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect);
  14. static void rtgui_hz_file_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect);
  15. const struct rtgui_font_engine rtgui_hz_file_font_engine =
  16. {
  17. RT_NULL,
  18. rtgui_hz_file_font_load,
  19. rtgui_hz_file_font_draw_text,
  20. rtgui_hz_file_font_get_metrics
  21. };
  22. SPLAY_PROTOTYPE(cache_tree, hz_cache, hz_node, _font_cache_compare);
  23. SPLAY_GENERATE (cache_tree, hz_cache, hz_node, _font_cache_compare);
  24. static int _font_cache_compare(struct hz_cache* cache_1, struct hz_cache* cache_2)
  25. {
  26. if (cache_1->hz_id > cache_2->hz_id) return 1;
  27. if (cache_1->hz_id < cache_2->hz_id) return -1;
  28. return 0;
  29. }
  30. static rt_uint8_t* _font_cache_get(struct rtgui_hz_file_font* font, rt_uint16_t hz_id)
  31. {
  32. rt_uint32_t seek;
  33. struct hz_cache *cache, search;
  34. search.hz_id = hz_id;
  35. /* enter critical */
  36. rtgui_enter_critical();
  37. cache = SPLAY_FIND(cache_tree, &(font->cache_root), &search);
  38. if (cache != RT_NULL)
  39. {
  40. /* exit critical */
  41. rtgui_exit_critical();
  42. /* found it */
  43. return (rt_uint8_t*)(cache + 1);
  44. }
  45. /* exit critical */
  46. rtgui_exit_critical();
  47. /* can not find it, load to cache */
  48. cache = (struct hz_cache*) rtgui_malloc(sizeof(struct hz_cache) + font->font_data_size);
  49. if (cache == RT_NULL)
  50. return RT_NULL; /* no memory yet */
  51. cache->hz_id = hz_id;
  52. seek = 94 * (((hz_id & 0xff) - 0xA0) - 1) + ((hz_id >> 8) - 0xA0) - 1;
  53. seek *= font->font_data_size;
  54. /* read hz font data */
  55. if ((lseek(font->fd, seek, SEEK_SET) < 0) ||
  56. read(font->fd, (char*)(cache + 1), font->font_data_size) !=
  57. font->font_data_size)
  58. {
  59. rtgui_free(cache);
  60. return RT_NULL;
  61. }
  62. /* enter critical */
  63. rtgui_enter_critical();
  64. /* insert to cache */
  65. SPLAY_INSERT(cache_tree, &(font->cache_root), cache);
  66. font->cache_size ++;
  67. if (font->cache_size > HZ_CACHE_MAX)
  68. {
  69. /* remove a cache */
  70. struct hz_cache* left;
  71. left = font->cache_root.sph_root;
  72. while (SPLAY_LEFT(left, hz_node) != RT_NULL) left = SPLAY_LEFT(left, hz_node);
  73. /* remove the left node */
  74. SPLAY_REMOVE(cache_tree, &(font->cache_root), left);
  75. rtgui_free(left);
  76. font->cache_size --;
  77. }
  78. /* exit critical */
  79. rtgui_exit_critical();
  80. return (rt_uint8_t*)(cache + 1);
  81. }
  82. static void rtgui_hz_file_font_load(struct rtgui_font* font)
  83. {
  84. struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
  85. RT_ASSERT(hz_file_font != RT_NULL);
  86. hz_file_font->fd = open(hz_file_font->font_fn, O_RDONLY, 0);
  87. }
  88. static void _rtgui_hz_file_font_draw_text(struct rtgui_hz_file_font* hz_file_font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
  89. {
  90. rt_uint8_t* str;
  91. rtgui_color_t bc;
  92. rt_uint16_t style;
  93. register rt_base_t h, word_bytes;
  94. /* get text style */
  95. style = rtgui_dc_get_gc(dc)->textstyle;
  96. bc = rtgui_dc_get_gc(dc)->background;
  97. /* drawing height */
  98. h = (hz_file_font->font_size + rect->y1 > rect->y2)?
  99. rect->y2 - rect->y1 : hz_file_font->font_size;
  100. word_bytes = (hz_file_font->font_size + 7) / 8;
  101. str = (rt_uint8_t*)text;
  102. while (len > 0 && rect->x1 < rect->x2)
  103. {
  104. const rt_uint8_t* font_ptr;
  105. register rt_base_t i, j, k;
  106. /* get font pixel data */
  107. font_ptr = _font_cache_get(hz_file_font, *str | (*(str+1) << 8));
  108. /* draw word */
  109. for (i=0; i < h; i ++)
  110. {
  111. for (j=0; j < word_bytes; j++)
  112. for (k=0; k < 8; k++)
  113. {
  114. if ( ((font_ptr[i*2 + j] >> (7-k)) & 0x01) != 0 &&
  115. (rect->x1 + 8 * j + k < rect->x2))
  116. {
  117. rtgui_dc_draw_point(dc, rect->x1 + 8*j + k, rect->y1 + i);
  118. }
  119. else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
  120. {
  121. rtgui_dc_draw_color_point(dc, rect->x1 + 8*j + k, rect->y1 + i, bc);
  122. }
  123. }
  124. }
  125. /* move x to next character */
  126. rect->x1 += hz_file_font->font_size;
  127. str += 2;
  128. len -= 2;
  129. }
  130. }
  131. static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t length, struct rtgui_rect* rect)
  132. {
  133. rt_uint32_t len;
  134. struct rtgui_font *efont;
  135. struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
  136. RT_ASSERT(dc != RT_NULL);
  137. RT_ASSERT(hz_file_font != RT_NULL);
  138. /* get English font */
  139. efont = rtgui_font_refer("asc", hz_file_font->font_size);
  140. if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
  141. while (length > 0)
  142. {
  143. len = 0;
  144. while (((rt_uint8_t)*(text + len)) < 0x80 && *(text + len)) len ++;
  145. /* draw text with English font */
  146. if (len > 0)
  147. {
  148. rtgui_font_draw(efont, dc, text, len, rect);
  149. text += len;
  150. length -= len;
  151. }
  152. len = 0;
  153. while (((rt_uint8_t)*(text + len)) >= 0x80) len ++;
  154. if (len > 0)
  155. {
  156. _rtgui_hz_file_font_draw_text(hz_file_font, dc, text, len, rect);
  157. text += len;
  158. length -= len;
  159. }
  160. }
  161. rtgui_font_derefer(efont);
  162. }
  163. static void rtgui_hz_file_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect)
  164. {
  165. struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
  166. RT_ASSERT(hz_file_font != RT_NULL);
  167. /* set metrics rect */
  168. rect->x1 = rect->y1 = 0;
  169. rect->x2 = (rt_int16_t)(hz_file_font->font_size/2 * rt_strlen((const char*)text));
  170. rect->y2 = hz_file_font->font_size;
  171. }
  172. #endif