text3.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* text draw truetypefont
  2. *
  3. * 2004/01/30
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #include <grass/config.h>
  9. #ifdef HAVE_ICONV_H
  10. #include <iconv.h>
  11. #endif
  12. #ifdef HAVE_FT2BUILD_H
  13. #include <ft2build.h>
  14. #include FT_FREETYPE_H
  15. #endif
  16. #include <grass/gis.h>
  17. #include "driver.h"
  18. #include "driverlib.h"
  19. /*#define DEBUG_LOG(S) {FILE *fp = fopen("debug.TXT","a");fputs(S,fp);fclose(fp);} */
  20. /*#define DEBUG_LOG_INT(D) {FILE *fp = fopen("debug.TXT","a");fprintf(fp,"%d",D);fclose(fp);} */
  21. /*#define DEBUG_LOG_DOUBLE(D) {FILE *fp = fopen("debug.TXT","a");fprintf(fp,"%f",D);fclose(fp);} */
  22. struct rectangle
  23. {
  24. double t, b, l, r;
  25. };
  26. #ifdef HAVE_FT2BUILD_H
  27. static int convert_str(const char *, const char *, unsigned char **);
  28. static void release_convert_str(unsigned char *);
  29. static void set_matrix(FT_Matrix *);
  30. static void draw_text(FT_Face, FT_Vector *, FT_Matrix *,
  31. const unsigned char *, int, int, struct rectangle *);
  32. static void draw_bitmap(FT_Bitmap *, FT_Int, FT_Int);
  33. static void set_text_box(FT_Bitmap *, FT_Int, FT_Int, struct rectangle *);
  34. #endif
  35. static void draw_main(double x, double y, const char *string,
  36. struct rectangle *box)
  37. {
  38. #ifdef HAVE_FT2BUILD_H
  39. FT_Library library;
  40. FT_Face face;
  41. FT_Matrix matrix;
  42. /*FT_UInt glyph_index; */
  43. FT_Vector pen;
  44. FT_Error ans;
  45. const char *filename;
  46. const char *encoding;
  47. int font_index;
  48. unsigned char *out;
  49. int outlen;
  50. /* get file name */
  51. filename = font_get_freetype_name();
  52. encoding = font_get_encoding();
  53. font_index = font_get_index();
  54. /* set freetype */
  55. ans = FT_Init_FreeType(&library);
  56. if (ans) {
  57. /* DEBUG_LOG("Text3 error: ft init\n"); */
  58. return;
  59. }
  60. ans = FT_New_Face(library, filename, font_index, &face);
  61. if (ans == FT_Err_Unknown_File_Format) {
  62. /* DEBUG_LOG("Text3 error: ft new face 1\n"); */
  63. FT_Done_FreeType(library);
  64. return;
  65. }
  66. else if (ans) {
  67. /* DEBUG_LOG("Text3 error: ft new face 2\n"); */
  68. FT_Done_FreeType(library);
  69. return;
  70. }
  71. /* ans = FT_Set_Pixel_Sizes(face,10,10); */
  72. /* ans = FT_Set_Char_Size(face,text_size_x*64,text_size_y*64,0,0); */
  73. /* ans = FT_Set_Char_Size(face,10*64,0,72,0); */
  74. /* ans = FT_Set_Char_Size(face,text_size_x*64,text_size_y*64,72,72); */
  75. ans = FT_Set_Char_Size(face,
  76. (int)(text_size_x * 64),
  77. (int)(text_size_y * 64),
  78. 100, 100);
  79. if (ans) {
  80. /* DEBUG_LOG("Text3 error: ft set size\n"); */
  81. FT_Done_Face(face);
  82. FT_Done_FreeType(library);
  83. return;
  84. }
  85. /* init point */
  86. pen.x = x * 64;
  87. /* pen.y = 0; */
  88. pen.y = (screen_height - y) * 64;
  89. /* convert string to:shift-jis from:encoding */
  90. outlen = convert_str(encoding, string, &out);
  91. /* set matrix */
  92. set_matrix(&matrix);
  93. /* draw */
  94. draw_text(face, &pen, &matrix, out, outlen, 0, box);
  95. /* release */
  96. release_convert_str(out);
  97. /* FT_done */
  98. FT_Done_Face(face);
  99. FT_Done_FreeType(library);
  100. #endif
  101. }
  102. #ifdef HAVE_FT2BUILD_H
  103. static void set_matrix(FT_Matrix * matrix)
  104. {
  105. /* rotation is in radians */
  106. matrix->xx = (FT_Fixed) ( text_cosrot * 0x10000);
  107. matrix->xy = (FT_Fixed) (-text_sinrot * 0x10000);
  108. matrix->yx = (FT_Fixed) ( text_sinrot * 0x10000);
  109. matrix->yy = (FT_Fixed) ( text_cosrot * 0x10000);
  110. }
  111. static int convert_str(const char *from, const char *in, unsigned char **out)
  112. {
  113. size_t len, i, res;
  114. const unsigned char *p1;
  115. unsigned char *p2;
  116. len = strlen(in);
  117. res = 2 * (len + 1);
  118. *out = G_calloc(1, res);
  119. p1 = (const unsigned char *)in;
  120. p2 = *out;
  121. #ifdef HAVE_ICONV_H
  122. {
  123. iconv_t cd;
  124. i = res;
  125. cd = iconv_open("UCS-2BE", from);
  126. if (cd == (iconv_t) -1)
  127. return -1;
  128. if (iconv(cd, (char **)&p1, &len, (char **)&p2, &i) == (size_t) -1)
  129. return -1;
  130. iconv_close(cd);
  131. res -= i;
  132. }
  133. #else
  134. for (i = 0; i <= len; i++)
  135. /* Pad each character out to 2 bytes, i.e. UCS-2 Big Endian encoding
  136. * (note low byte has already been zeroed by G_calloc() call) */
  137. p2[2 * i + 1] = p1[i];
  138. res = 2 * len;
  139. #endif
  140. return res;
  141. }
  142. static void release_convert_str(unsigned char *out)
  143. {
  144. G_free(out);
  145. }
  146. static void draw_text(FT_Face face, FT_Vector * pen, FT_Matrix * matrix,
  147. const unsigned char *out, int len, int color,
  148. struct rectangle *box)
  149. {
  150. FT_ULong ch;
  151. FT_Error ans;
  152. FT_GlyphSlot slot = face->glyph;
  153. int i;
  154. for (i = 0; i < len; i += 2) {
  155. ch = (out[i] << 8) | out[i + 1];
  156. if (ch == 10)
  157. continue;
  158. /* transform */
  159. FT_Set_Transform(face, matrix, pen);
  160. /* get glyph image */
  161. ans = FT_Load_Char(face, ch, FT_LOAD_NO_BITMAP);
  162. if (ans)
  163. continue;
  164. ans = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
  165. if (ans)
  166. continue;
  167. /* draw bitmap */
  168. if (!box)
  169. draw_bitmap(&slot->bitmap, slot->bitmap_left,
  170. screen_height - slot->bitmap_top);
  171. else
  172. set_text_box(&slot->bitmap, slot->bitmap_left,
  173. screen_height - slot->bitmap_top, box);
  174. /* increment pen position */
  175. pen->x += slot->advance.x;
  176. pen->y += slot->advance.y;
  177. }
  178. }
  179. static void set_text_box(FT_Bitmap *bitmap, FT_Int x, FT_Int y, struct rectangle *box)
  180. {
  181. FT_Int xMax = x + bitmap->width;
  182. FT_Int yMax = y + bitmap->rows;
  183. if ((x == xMax) || (y == yMax))
  184. return;
  185. if (x < box->l)
  186. box->l = x;
  187. if (xMax > box->r)
  188. box->r = xMax;
  189. if (y < box->t)
  190. box->t = y;
  191. if (yMax > box->b)
  192. box->b = yMax;
  193. }
  194. static void draw_bitmap(FT_Bitmap * bitmap, FT_Int x, FT_Int y)
  195. {
  196. static unsigned char *buf;
  197. static int nalloc;
  198. int w, h;
  199. int bw = bitmap->width;
  200. int bh = bitmap->rows;
  201. const unsigned char *sbuf = bitmap->buffer;
  202. int offset, i, j;
  203. double x1, y1, x2, y2;
  204. x1 = x;
  205. y1 = y;
  206. x2 = x1 + bw;
  207. y2 = y1 + bh;
  208. w = x2 - x1;
  209. h = y2 - y1;
  210. if (w <= 0 || h <= 0)
  211. return;
  212. offset = ((int)y1 - y) * bw + (int)x1 - x;
  213. if (nalloc < w * h) {
  214. nalloc = w * h;
  215. buf = G_realloc(buf, nalloc);
  216. }
  217. for (j = 0; j < h; j++)
  218. for (i = 0; i < w; i++)
  219. buf[j * w + i] = sbuf[offset + j * bw + i];
  220. COM_Pos_abs(x1, y1);
  221. COM_Bitmap(w, h, 128, buf);
  222. }
  223. #endif
  224. void soft_text_freetype(const char *string)
  225. {
  226. draw_main(cur_x, cur_y, string, NULL);
  227. }
  228. void get_text_ext_freetype(const char *string, double *top, double *bot, double *left, double *rite)
  229. {
  230. struct rectangle box;
  231. box.t = 1e300;
  232. box.b = -1e300;
  233. box.l = 1e300;
  234. box.r = -1e300;
  235. draw_main(cur_x, cur_y, string, &box);
  236. *top = box.t;
  237. *bot = box.b;
  238. *left = box.l;
  239. *rite = box.r;
  240. }