font_hz_file.c 6.5 KB

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