font_fnt.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * rockbox fnt font engine
  3. */
  4. #include <rtgui/font_fnt.h>
  5. #include <rtgui/rtgui_system.h>
  6. static void rtgui_fnt_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect);
  7. static void rtgui_fnt_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
  8. const struct rtgui_font_engine fnt_font_engine =
  9. {
  10. RT_NULL,
  11. RT_NULL,
  12. rtgui_fnt_font_draw_text,
  13. rtgui_fnt_font_get_metrics
  14. };
  15. void rtgui_fnt_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect)
  16. {
  17. int ch, i, j, c, width;
  18. rt_uint32_t position;
  19. struct fnt_font *fnt;
  20. rt_uint8_t *data_ptr;
  21. fnt = (struct fnt_font*)font->data;
  22. RT_ASSERT(fnt != RT_NULL);
  23. while (len)
  24. {
  25. /* get character */
  26. ch = *text;
  27. /* NOTE: we only support asc character right now */
  28. if (ch > 0x80)
  29. {
  30. text += 1; len -= 1;
  31. continue;
  32. }
  33. /* get position and width */
  34. if (fnt->offset == RT_NULL)
  35. {
  36. width = fnt->header.max_width;
  37. position = (ch - fnt->header.first_char) * width * ((fnt->header.height + 7)/8);
  38. }
  39. else
  40. {
  41. width = fnt->width[ch - fnt->header.first_char];
  42. position = fnt->offset[ch - fnt->header.first_char];
  43. }
  44. /* draw a character */
  45. data_ptr = (rt_uint8_t*)&fnt->bits[position];
  46. for (i = 0; i < width; i ++) /* x */
  47. {
  48. for (j = 0; j < 8; j ++) /* y */
  49. {
  50. for (c = 0; c < (fnt->header.height + 7)/8; c ++)
  51. {
  52. /* check drawable region */
  53. if ((rect->x1 + i > rect->x2) || (rect->y1 + c * 8 + j > rect->y2))
  54. continue;
  55. if (data_ptr[i + c * width] & (1 << j))
  56. rtgui_dc_draw_point(dc, rect->x1 + i, rect->y1 + c * 8 + j);
  57. }
  58. }
  59. }
  60. rect->x1 += width;
  61. text += 1;
  62. len -= 1;
  63. }
  64. }
  65. void rtgui_fnt_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
  66. {
  67. int ch;
  68. struct fnt_font *fnt;
  69. fnt = (struct fnt_font*)font->data;
  70. RT_ASSERT(fnt != RT_NULL);
  71. rt_memset(rect, 0x00, sizeof(rtgui_rect_t));
  72. rect->y2 = fnt->header.height;
  73. while (*text)
  74. {
  75. if (fnt->width == RT_NULL)
  76. {
  77. /* fixed width font */
  78. rect->x2 += fnt->header.max_width;
  79. }
  80. else
  81. {
  82. ch = *text;
  83. /* NOTE: we only support asc character right now */
  84. if (ch > 0x80)
  85. {
  86. text += 1;
  87. continue;
  88. }
  89. rect->x2 += fnt->width[ch - fnt->header.first_char];
  90. }
  91. text += 1;
  92. }
  93. }
  94. #ifdef RTGUI_USING_FNT_FILE
  95. #include <dfs_posix.h>
  96. rt_inline int readbyte(int fd, unsigned char *cp)
  97. {
  98. unsigned char buf[1];
  99. if (read(fd, buf, 1) != 1)
  100. return 0;
  101. *cp = buf[0];
  102. return 1;
  103. }
  104. rt_inline int readshort(int fd, unsigned short *sp)
  105. {
  106. unsigned char buf[2];
  107. if (read(fd, buf, 2) != 2)
  108. return 0;
  109. *sp = buf[0] | (buf[1] << 8);
  110. return 1;
  111. }
  112. rt_inline int readlong(int fd, rt_uint32_t *lp)
  113. {
  114. unsigned char buf[4];
  115. if (read(fd, buf, 4) != 4)
  116. return 0;
  117. *lp = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
  118. return 1;
  119. }
  120. rt_inline int readstr(int fd, char *buf, int count)
  121. {
  122. return read(fd, buf, count);
  123. }
  124. struct rtgui_font *fnt_font_create(const char* filename, const char* font_family)
  125. {
  126. int fd = -1;
  127. rt_uint32_t index;
  128. struct rtgui_font *font = RT_NULL;
  129. struct fnt_font *fnt = RT_NULL;
  130. struct fnt_header *fnt_header;
  131. fd = open(filename, O_RDONLY, 0);
  132. if (fd < 0)
  133. {
  134. goto __exit;
  135. }
  136. font = (struct rtgui_font*) rtgui_malloc (sizeof(struct rtgui_font));
  137. if (font == RT_NULL) goto __exit;
  138. fnt = (struct fnt_font*) rtgui_malloc (sizeof(struct fnt_font));
  139. if (fnt == RT_NULL) goto __exit;
  140. rt_memset(fnt, 0x00, sizeof(struct fnt_font));
  141. font->data = (void*)fnt;
  142. fnt_header = &(fnt->header);
  143. if (readstr(fd, fnt_header->version, 4) != 4) goto __exit;
  144. if (!readshort(fd, &fnt_header->max_width)) goto __exit;
  145. if (!readshort(fd, &fnt_header->height)) goto __exit;
  146. if (!readshort(fd, &fnt_header->ascent)) goto __exit;
  147. if (!readshort(fd, &fnt_header->depth)) goto __exit;
  148. if (!readlong(fd, &fnt_header->first_char)) goto __exit;
  149. if (!readlong(fd, &fnt_header->default_char)) goto __exit;
  150. if (!readlong(fd, &fnt_header->size)) goto __exit;
  151. if (!readlong(fd, &fnt_header->nbits)) goto __exit;
  152. if (!readlong(fd, &fnt_header->noffset)) goto __exit;
  153. if (!readlong(fd, &fnt_header->nwidth)) goto __exit;
  154. fnt->bits = (MWIMAGEBITS*) rtgui_malloc (fnt_header->nbits * sizeof(MWIMAGEBITS));
  155. if (fnt->bits == RT_NULL) goto __exit;
  156. /* read data */
  157. if (readstr(fd, &(fnt->bits[0]), fnt_header->nbits) != fnt_header->nbits) goto __exit;
  158. /* check boundary */
  159. if (fnt_header->nbits & 0x01)
  160. {
  161. rt_uint16_t pad;
  162. readshort(fd, &pad);
  163. pad = pad; /* skip warning */
  164. }
  165. if (fnt_header->noffset != 0)
  166. {
  167. fnt->offset = rtgui_malloc (fnt_header->noffset * sizeof(rt_uint32_t));
  168. if (fnt->offset == RT_NULL) goto __exit;
  169. for (index = 0; index < fnt_header->noffset; index ++)
  170. {
  171. if (!readshort(fd, &(fnt->offset[index]))) goto __exit;
  172. }
  173. }
  174. if (fnt_header->nwidth != 0)
  175. {
  176. fnt->width = rtgui_malloc (fnt_header->nwidth * sizeof(rt_uint8_t));
  177. if (fnt->width == RT_NULL) goto __exit;
  178. for (index = 0; index < fnt_header->nwidth; index ++)
  179. {
  180. if (!readbyte(fd, &(fnt->width[index]))) goto __exit;
  181. }
  182. }
  183. close(fd);
  184. font->family = rt_strdup(font_family);
  185. font->height = fnt->header.height;
  186. font->refer_count = 0;
  187. font->engine = &fnt_font_engine;
  188. /* add to system */
  189. rtgui_font_system_add_font(font);
  190. return font;
  191. __exit:
  192. if (fd >= 0) close(fd);
  193. if (fnt != RT_NULL)
  194. {
  195. if (fnt->bits != RT_NULL) rtgui_free(fnt->bits);
  196. if (fnt->offset != RT_NULL) rtgui_free(fnt->offset);
  197. if (fnt->width != RT_NULL) rtgui_free(fnt->width);
  198. rtgui_free(fnt);
  199. }
  200. if (font != RT_NULL)
  201. {
  202. rtgui_free(font);
  203. }
  204. return RT_NULL;
  205. }
  206. #endif