text3.c 7.2 KB

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