font_hz_file.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * File : font_hz_file.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2010-09-15 Bernard first version
  23. */
  24. /*
  25. * Cached HZ font engine
  26. */
  27. #include <rtgui/dc.h>
  28. #include <rtgui/font.h>
  29. #include <rtgui/tree.h>
  30. #include <rtgui/rtgui_system.h>
  31. #ifdef RTGUI_USING_HZ_FILE
  32. #ifdef _WIN32_NATIVE
  33. #include <fcntl.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <io.h>
  37. #define open _open
  38. #define close _close
  39. #define read _read
  40. #define write _write
  41. #define unlink _unlink
  42. #else
  43. #include <dfs_posix.h>
  44. #endif
  45. #define HZ_CACHE_MAX 64
  46. static int _font_cache_compare(struct hz_cache *node1, struct hz_cache *node2);
  47. static void rtgui_hz_file_font_load(struct rtgui_font *font);
  48. 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);
  49. static void rtgui_hz_file_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
  50. const struct rtgui_font_engine rtgui_hz_file_font_engine =
  51. {
  52. RT_NULL,
  53. rtgui_hz_file_font_load,
  54. rtgui_hz_file_font_draw_text,
  55. rtgui_hz_file_font_get_metrics
  56. };
  57. SPLAY_PROTOTYPE(cache_tree, hz_cache, hz_node, _font_cache_compare);
  58. SPLAY_GENERATE(cache_tree, hz_cache, hz_node, _font_cache_compare);
  59. static int _font_cache_compare(struct hz_cache *cache_1, struct hz_cache *cache_2)
  60. {
  61. if (cache_1->hz_id > cache_2->hz_id) return 1;
  62. if (cache_1->hz_id < cache_2->hz_id) return -1;
  63. return 0;
  64. }
  65. static rt_uint8_t *_font_cache_get(struct rtgui_hz_file_font *font, rt_uint16_t hz_id)
  66. {
  67. rt_uint32_t seek;
  68. struct hz_cache *cache, search;
  69. search.hz_id = hz_id;
  70. /* enter critical */
  71. rtgui_enter_critical();
  72. cache = SPLAY_FIND(cache_tree, &(font->cache_root), &search);
  73. if (cache != RT_NULL)
  74. {
  75. /* exit critical */
  76. rtgui_exit_critical();
  77. /* found it */
  78. return (rt_uint8_t *)(cache + 1);
  79. }
  80. /* exit critical */
  81. rtgui_exit_critical();
  82. /* can not find it, load to cache */
  83. cache = (struct hz_cache *) rtgui_malloc(sizeof(struct hz_cache) + font->font_data_size);
  84. if (cache == RT_NULL)
  85. return RT_NULL; /* no memory yet */
  86. cache->hz_id = hz_id;
  87. seek = 94 * (((hz_id & 0xff) - 0xA0) - 1) + ((hz_id >> 8) - 0xA0) - 1;
  88. seek *= font->font_data_size;
  89. /* read hz font data */
  90. if ((lseek(font->fd, seek, SEEK_SET) < 0) ||
  91. read(font->fd, (char *)(cache + 1), font->font_data_size) !=
  92. font->font_data_size)
  93. {
  94. rtgui_free(cache);
  95. return RT_NULL;
  96. }
  97. /* enter critical */
  98. rtgui_enter_critical();
  99. if (font->cache_size >= HZ_CACHE_MAX)
  100. {
  101. /* remove a cache */
  102. struct hz_cache *left;
  103. left = font->cache_root.sph_root;
  104. while (SPLAY_LEFT(left, hz_node) != RT_NULL) left = SPLAY_LEFT(left, hz_node);
  105. /* remove the left node */
  106. SPLAY_REMOVE(cache_tree, &(font->cache_root), left);
  107. rtgui_free(left);
  108. font->cache_size --;
  109. }
  110. /* insert to cache */
  111. SPLAY_INSERT(cache_tree, &(font->cache_root), cache);
  112. font->cache_size ++;
  113. /* exit critical */
  114. rtgui_exit_critical();
  115. return (rt_uint8_t *)(cache + 1);
  116. }
  117. static void rtgui_hz_file_font_load(struct rtgui_font *font)
  118. {
  119. struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
  120. RT_ASSERT(hz_file_font != RT_NULL);
  121. hz_file_font->fd = open(hz_file_font->font_fn, O_RDONLY, 0);
  122. if (hz_file_font->fd < 0)
  123. {
  124. rt_kprintf("RTGUI: could not open the font file:%s\n", hz_file_font->font_fn);
  125. rt_kprintf("RTGUI: please mount the fs first and make sure the file is there\n");
  126. }
  127. }
  128. 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)
  129. {
  130. rt_uint8_t *str;
  131. rtgui_color_t bc;
  132. rt_uint16_t style;
  133. register rt_base_t h, word_bytes;
  134. /* get text style */
  135. style = rtgui_dc_get_gc(dc)->textstyle;
  136. bc = rtgui_dc_get_gc(dc)->background;
  137. /* drawing height */
  138. h = (hz_file_font->font_size + rect->y1 > rect->y2) ?
  139. rect->y2 - rect->y1 : hz_file_font->font_size;
  140. word_bytes = (hz_file_font->font_size + 7) / 8;
  141. str = (rt_uint8_t *)text;
  142. while (len > 0 && rect->x1 < rect->x2)
  143. {
  144. const rt_uint8_t *font_ptr;
  145. register rt_base_t i, j, k;
  146. /* get font pixel data */
  147. font_ptr = _font_cache_get(hz_file_font, *str | (*(str + 1) << 8));
  148. /* draw word */
  149. for (i = 0; i < h; i ++)
  150. {
  151. for (j = 0; j < word_bytes; j++)
  152. for (k = 0; k < 8; k++)
  153. {
  154. if (((font_ptr[i * word_bytes + j] >> (7 - k)) & 0x01) != 0 &&
  155. (rect->x1 + 8 * j + k < rect->x2))
  156. {
  157. rtgui_dc_draw_point(dc, rect->x1 + 8 * j + k, rect->y1 + i);
  158. }
  159. else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
  160. {
  161. rtgui_dc_draw_color_point(dc, rect->x1 + 8 * j + k, rect->y1 + i, bc);
  162. }
  163. }
  164. }
  165. /* move x to next character */
  166. rect->x1 += hz_file_font->font_size;
  167. str += 2;
  168. len -= 2;
  169. }
  170. }
  171. 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)
  172. {
  173. rt_uint32_t len;
  174. struct rtgui_font *efont;
  175. struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
  176. struct rtgui_rect text_rect;
  177. RT_ASSERT(dc != RT_NULL);
  178. RT_ASSERT(hz_file_font != RT_NULL);
  179. rtgui_font_get_metrics(rtgui_dc_get_gc(dc)->font, text, &text_rect);
  180. rtgui_rect_move_to_align(rect, &text_rect, RTGUI_DC_TEXTALIGN(dc));
  181. /* get English font */
  182. efont = rtgui_font_refer("asc", hz_file_font->font_size);
  183. if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
  184. while (length > 0)
  185. {
  186. len = 0;
  187. while (((rt_uint8_t) * (text + len)) < 0x80 && *(text + len) && len < length) len ++;
  188. /* draw text with English font */
  189. if (len > 0)
  190. {
  191. rtgui_font_draw(efont, dc, text, len, &text_rect);
  192. text += len;
  193. length -= len;
  194. }
  195. len = 0;
  196. while (((rt_uint8_t) * (text + len)) >= 0x80 && len < length) len ++;
  197. if (len > 0)
  198. {
  199. _rtgui_hz_file_font_draw_text(hz_file_font, dc, text, len, &text_rect);
  200. text += len;
  201. length -= len;
  202. }
  203. }
  204. rtgui_font_derefer(efont);
  205. }
  206. static void rtgui_hz_file_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
  207. {
  208. struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
  209. RT_ASSERT(hz_file_font != RT_NULL);
  210. /* set metrics rect */
  211. rect->x1 = rect->y1 = 0;
  212. rect->x2 = (rt_int16_t)(hz_file_font->font_size / 2 * rt_strlen((const char *)text));
  213. rect->y2 = hz_file_font->font_size;
  214. }
  215. #endif