123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- /*!
- \file lib/cairodriver/text.c
- \brief GRASS cairo display driver - text subroutines
- (C) 2007-2008 by Lars Ahlzen and the GRASS Development Team
-
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
-
- \author Lars Ahlzen <lars ahlzen.com> (original contibutor)
- \author Glynn Clements
- */
- #include <grass/glocale.h>
- #include "cairodriver.h"
- #if CAIRO_HAS_FT_FONT
- #include <cairo-ft.h>
- #include <fontconfig/fontconfig.h>
- #endif
- #ifdef HAVE_ICONV_H
- #include <iconv.h>
- #endif
- static char *convert(const char *in)
- {
- size_t ilen, olen;
- char *out;
- ilen = strlen(in);
- olen = 3 * ilen + 1;
- out = G_malloc(olen);
- #ifdef HAVE_ICONV_H
- {
- const char *encoding = font_get_encoding();
- char *p1 = (char *) in;
- char *p2 = out;
- size_t ret;
- iconv_t cd;
- if ((cd = iconv_open("UTF-8", encoding)) < 0)
- G_fatal_error(_("Unable to convert from <%s> to UTF-8"),
- encoding);
- ret = iconv(cd, &p1, &ilen, &p2, &olen);
- iconv_close(cd);
- *p2++ = '\0';
- if (ret > 0)
- G_warning(_("Some characters could not be converted to UTF-8"));
- }
- #else
- {
- const unsigned char *p1 = (const unsigned char *) in;
- unsigned char *p2 = (unsigned char *) out;
- int i, j;
- for (i = j = 0; i < ilen; i++) {
- int c = p1[i];
- if (c < 0x80)
- p2[j++] = c;
- else {
- p2[j++] = 0xC0 + (c >> 6);
- p2[j++] = 0x80 + (c & 0x3F);
- }
- }
- p2[j++] = '\0';
- }
- #endif
- return out;
- }
- static void set_matrix(void)
- {
- static cairo_matrix_t mat;
- if (matrix_valid)
- return;
- cairo_matrix_init_identity(&mat);
- cairo_matrix_scale(&mat, text_size_x, text_size_y);
- cairo_matrix_rotate(&mat, -text_rotation * M_PI / 180);
- cairo_set_font_matrix(cairo, &mat);
- matrix_valid = 1;
- }
- /*!
- \brief Draw text
-
- \param str string to be drawn
- */
- void Cairo_Text(const char *str)
- {
- char *utf8 = convert(str);
- if (!utf8)
- return;
- set_matrix();
- cairo_move_to(cairo, cur_x, cur_y);
- cairo_show_text(cairo, utf8);
- G_free(utf8);
- ca.modified = 1;
- }
- /*
- \brief Get text bounding box
- \param str string
- \param[out] t,b,l,r top, bottom, left, right corner
- */
- void Cairo_text_box(const char *str, double *t, double *b, double *l, double *r)
- {
- char *utf8 = convert(str);
- cairo_text_extents_t ext;
- if (!utf8)
- return;
- set_matrix();
- cairo_text_extents(cairo, utf8, &ext);
- G_free(utf8);
- *l = cur_x + ext.x_bearing;
- *r = cur_x + ext.x_bearing + ext.width;
- *t = cur_y + ext.y_bearing;
- *b = cur_y + ext.y_bearing + ext.height;
- }
- static void set_font_toy(const char *name)
- {
- char *font = G_store(name);
- cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL;
- cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL;
- for (;;) {
- char *p = strrchr(font, '-');
- if (!p)
- break;
- if (G_strcasecmp(p, "-bold") == 0)
- weight = CAIRO_FONT_WEIGHT_BOLD;
- else if (strcasecmp(p, "-italic") == 0)
- slant = CAIRO_FONT_SLANT_ITALIC;
- else if (G_strcasecmp(p, "-oblique") == 0)
- slant = CAIRO_FONT_SLANT_OBLIQUE;
- else
- break;
- *p = '\0';
- }
- cairo_select_font_face(cairo, font, slant, weight);
- G_free(font);
- }
- #if CAIRO_HAS_FT_FONT
- static void fc_init(void)
- {
- static int initialized;
- if (!initialized) {
- FcInit();
- initialized = 1;
- }
- }
- static void set_font_fc(const char *name)
- {
- static cairo_font_face_t *face;
- FcPattern *pattern;
- FcResult result;
- fc_init();
- if (face) {
- cairo_font_face_destroy(face);
- face = NULL;
- }
- pattern = FcNameParse(name);
- FcDefaultSubstitute(pattern);
- FcConfigSubstitute(FcConfigGetCurrent(), pattern, FcMatchPattern);
- pattern = FcFontMatch(FcConfigGetCurrent(), pattern, &result);
- face = cairo_ft_font_face_create_for_pattern(pattern);
- cairo_set_font_face(cairo, face);
- }
- static void font_list_fc(char ***list, int *count, int verbose)
- {
- FcPattern *pattern;
- FcObjectSet *objset;
- FcFontSet *fontset;
- char **fonts = *list;
- int num_fonts = *count;
- int i;
- fc_init();
- pattern = FcPatternCreate();
- objset = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (char *) NULL);
- fontset = FcFontList(NULL, pattern, objset);
- fonts = G_realloc(fonts, (num_fonts + fontset->nfont) * sizeof(char *));
- for (i = 0; i < fontset->nfont; i++) {
- char buf[1024];
- FcPattern *pat = fontset->fonts[i];
- FcChar8 *family = "", *style = "";
- FcPatternGetString(pat, FC_FAMILY, 0, &family);
- FcPatternGetString(pat, FC_STYLE , 0, &style );
- if (verbose)
- sprintf(buf, "%s:%s|%s:%s|%d|%s|%d|%s|",
- family, style, family, style, GFONT_DRIVER, "", 0, "utf-8");
- else
- sprintf(buf, "%s:%s", family, style);
- fonts[num_fonts++] = G_store(buf);
- }
- FcObjectSetDestroy(objset);
- FcPatternDestroy(pattern);
- FcFontSetDestroy (fontset);
- *list = fonts;
- *count = num_fonts;
- }
- #endif
- static const char *toy_fonts[12] = {
- "sans",
- "sans-italic",
- "sans-bold",
- "sans-bold-italic",
- "serif",
- "serif-italic",
- "serif-bold",
- "serif-bold-italic",
- "mono",
- "mono-italic",
- "mono-bold",
- "mono-bold-italic",
- };
- static const int num_toy_fonts = 12;
- static int is_toy_font(const char *name)
- {
- int i;
- for (i = 0; i < num_toy_fonts; i++)
- if (G_strcasecmp(name, toy_fonts[i]) == 0)
- return 1;
- return 0;
- }
- /*!
- \brief Set font
- \param name font name
- */
- void Cairo_set_font(const char *name)
- {
- #if CAIRO_HAS_FT_FONT
- if (is_toy_font(name))
- set_font_toy(name);
- else
- set_font_fc(name);
- #else
- set_font_toy(name);
- #endif
- }
- static void font_list_toy(char ***list, int *count, int verbose)
- {
- char **fonts = *list;
- int num_fonts = *count;
- int i;
- fonts = G_realloc(fonts, (num_fonts + num_toy_fonts) * sizeof(char *));
- for (i = 0; i < num_toy_fonts; i++) {
- char buf[256];
- if (verbose)
- sprintf(buf, "%s|%s|%d|%s|%d|%s|",
- toy_fonts[i], toy_fonts[i], GFONT_DRIVER, "", 0, "utf-8");
- else
- strcpy(buf, toy_fonts[i]);
- fonts[num_fonts++] = G_store(buf);
- }
- *list = fonts;
- *count = num_fonts;
- }
- /*!
- \brief Get list of fonts
- \param[out] list font list
- \param[out] count number of items in the list
- */
- void Cairo_font_list(char ***list, int *count)
- {
- font_list_toy(list, count, 0);
- #if CAIRO_HAS_FT_FONT
- font_list_fc(list, count, 0);
- #endif
- }
- /*!
- \brief Get fonts into
- \param[out] list font list
- \param[out] count number of items in the list
- */
- void Cairo_font_info(char ***list, int *count)
- {
- font_list_toy(list, count, 1);
- #if CAIRO_HAS_FT_FONT
- font_list_fc(list, count, 1);
- #endif
- }
|