Text.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include <grass/glocale.h>
  2. #include "cairodriver.h"
  3. #if CAIRO_HAS_FT_FONT
  4. #include <cairo-ft.h>
  5. #include <fontconfig/fontconfig.h>
  6. #endif
  7. #ifdef HAVE_ICONV_H
  8. #include <iconv.h>
  9. #endif
  10. static char *convert(const char *in)
  11. {
  12. size_t ilen, olen;
  13. char *out;
  14. ilen = strlen(in);
  15. olen = 3 * ilen + 1;
  16. out = G_malloc(olen);
  17. #ifdef HAVE_ICONV_H
  18. {
  19. char *p1 = (char *) in;
  20. char *p2 = out;
  21. size_t ret;
  22. iconv_t cd;
  23. if (!encoding)
  24. encoding = G_store("US-ASCII");
  25. if ((cd = iconv_open("UTF-8", encoding)) < 0)
  26. G_fatal_error(_("Unable to convert from <%s> to UTF-8"));
  27. ret = iconv(cd, &p1, &ilen, &p2, &olen);
  28. iconv_close(cd);
  29. *p2++ = '\0';
  30. if (ret > 0)
  31. G_warning(_("Some characters could not be converted to UTF-8"));
  32. }
  33. #else
  34. {
  35. const unsigned char *p1 = (const unsigned char *) in;
  36. unsigned char *p2 = (unsigned char *) out;
  37. int i, j;
  38. for (i = j = 0; i < len; i++) {
  39. int c = p1[i];
  40. if (c < 0x80)
  41. p2[j++] = c;
  42. else {
  43. p2[j++] = 0xC0 + (c >> 6);
  44. p2[j++] = 0x80 + (c & 0x3F);
  45. }
  46. }
  47. p2[j++] = '\0';
  48. }
  49. #endif
  50. return out;
  51. }
  52. static void set_matrix(void)
  53. {
  54. static cairo_matrix_t mat;
  55. if (matrix_valid)
  56. return;
  57. cairo_matrix_init_identity(&mat);
  58. cairo_matrix_scale(&mat, text_size_x * 25, text_size_y * 25);
  59. cairo_matrix_rotate(&mat, -text_rotation * M_PI / 180);
  60. cairo_set_font_matrix(cairo, &mat);
  61. matrix_valid = 1;
  62. }
  63. void Cairo_draw_text(const char *str)
  64. {
  65. char *utf8 = convert(str);
  66. if (!utf8)
  67. return;
  68. set_matrix();
  69. cairo_move_to(cairo, cur_x, cur_y);
  70. cairo_show_text(cairo, utf8);
  71. G_free(utf8);
  72. modified = 1;
  73. }
  74. void Cairo_text_box(const char *str, double *t, double *b, double *l, double *r)
  75. {
  76. char *utf8 = convert(str);
  77. cairo_text_extents_t ext;
  78. if (!utf8)
  79. return;
  80. set_matrix();
  81. cairo_text_extents(cairo, utf8, &ext);
  82. G_free(utf8);
  83. *l = cur_x + ext.x_bearing;
  84. *r = cur_x + ext.x_bearing + ext.width;
  85. *t = cur_x + ext.y_bearing;
  86. *b = cur_x + ext.y_bearing + ext.height;
  87. }
  88. static void set_font_toy(const char *name)
  89. {
  90. char *font = G_store(name);
  91. cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL;
  92. cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL;
  93. for (;;) {
  94. char *p = strrchr(font, '-');
  95. if (!p)
  96. break;
  97. if (G_strcasecmp(p, "-bold") == 0)
  98. weight = CAIRO_FONT_WEIGHT_BOLD;
  99. else if (strcasecmp(p, "-italic") == 0)
  100. slant = CAIRO_FONT_SLANT_ITALIC;
  101. else if (G_strcasecmp(p, "-oblique") == 0)
  102. slant = CAIRO_FONT_SLANT_OBLIQUE;
  103. else
  104. break;
  105. *p = '\0';
  106. }
  107. cairo_select_font_face(cairo, font, slant, weight);
  108. G_free(font);
  109. }
  110. #if CAIRO_HAS_FT_FONT
  111. static void set_font_fc(const char *name)
  112. {
  113. static cairo_font_face_t *face;
  114. static int initialized;
  115. FcPattern *pattern;
  116. FcResult result;
  117. if (!initialized) {
  118. FcInit();
  119. initialized = 1;
  120. }
  121. if (face) {
  122. cairo_font_face_destroy(face);
  123. face = NULL;
  124. }
  125. pattern = FcNameParse(name);
  126. FcDefaultSubstitute(pattern);
  127. FcConfigSubstitute(FcConfigGetCurrent(), pattern, FcMatchPattern);
  128. pattern = FcFontMatch(FcConfigGetCurrent(), pattern, &result);
  129. face = cairo_ft_font_face_create_for_pattern(pattern);
  130. cairo_set_font_face(cairo, face);
  131. }
  132. #endif
  133. static const char *toy_fonts[12] = {
  134. "sans",
  135. "sans-italic",
  136. "sans-bold",
  137. "sans-bold-italic",
  138. "serif",
  139. "serif-italic",
  140. "serif-bold",
  141. "serif-bold-italic",
  142. "mono",
  143. "mono-italic",
  144. "mono-bold",
  145. "mono-bold-italic",
  146. };
  147. static const int num_toy_fonts = 12;
  148. static int is_toy_font(const char *name)
  149. {
  150. int i;
  151. for (i = 0; i < num_toy_fonts; i++)
  152. if (G_strcasecmp(name, toy_fonts[i]) == 0)
  153. return 1;
  154. return 0;
  155. }
  156. void Cairo_set_font(const char *name)
  157. {
  158. #if CAIRO_HAS_FT_FONT
  159. if (is_toy_font(name))
  160. set_font_toy(name);
  161. else
  162. set_font_fc(name);
  163. #else
  164. set_font_toy(name);
  165. #endif
  166. }
  167. void Cairo_set_encoding(const char *enc)
  168. {
  169. if (encoding)
  170. G_free(encoding);
  171. encoding = G_store(enc);
  172. }
  173. void Cairo_text_size(double width, double height)
  174. {
  175. text_size_x = width;
  176. text_size_y = height;
  177. matrix_valid = 0;
  178. }
  179. void Cairo_text_rotation(double angle)
  180. {
  181. text_rotation = angle;
  182. matrix_valid = 0;
  183. }
  184. static void font_list_toy(char ***list, int *count, int verbose)
  185. {
  186. char **fonts = *list;
  187. int num_fonts = *count;
  188. int i;
  189. fonts = G_realloc(fonts, (num_fonts + num_toy_fonts) * sizeof(char *));
  190. for (i = 0; i < num_toy_fonts; i++) {
  191. char buf[256];
  192. sprintf(buf, "%s%s",
  193. toy_fonts[i],
  194. verbose ? "||1||0|utf-8|" : "");
  195. fonts[num_fonts++] = G_store(buf);
  196. }
  197. *list = fonts;
  198. *count = num_fonts;
  199. }
  200. void Cairo_font_list(char ***list, int *count)
  201. {
  202. font_list(list, count, 0);
  203. font_list_toy(list, count, 0);
  204. }
  205. void Cairo_font_info(char ***list, int *count)
  206. {
  207. font_list(list, count, 1);
  208. font_list_toy(list, count, 1);
  209. }