GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
Loading...
Searching...
No Matches
cairodriver/text.c
Go to the documentation of this file.
1/*!
2 \file lib/cairodriver/text.c
3
4 \brief GRASS cairo display driver - text subroutines
5
6 SPDX-FileCopyrightText: 2007-2008 Lars Ahlzen
7 SPDX-FileCopyrightText: GRASS Development Team
8 SPDX-License-Identifier: GPL-2.0-or-later
9
10 \author Lars Ahlzen <lars ahlzen.com> (original contributor)
11 \author Glynn Clements
12 */
13#if defined(_MSC_VER)
14#include <math.h>
15#endif
16
17#include <grass/glocale.h>
18#include "cairodriver.h"
19
20#if CAIRO_HAS_FT_FONT
21#include <cairo-ft.h>
22#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 10, 0) || defined(CAIRO_HAS_FC_FONT)
23#define USE_FONTCONFIG 1
24#include <fontconfig/fontconfig.h>
25#else
26#define USE_FONTCONFIG 0
27#endif
28#endif /* CAIRO_HAS_FT_FONT */
29
30#ifdef HAVE_ICONV_H
31#include <iconv.h>
32#endif
33
34static char *convert(const char *in)
35{
36 size_t ilen, olen;
37 char *out;
38
39 ilen = strlen(in);
40 olen = 3 * ilen + 1;
41
42 out = G_malloc(olen);
43
44#ifdef HAVE_ICONV_H
45 {
46 const char *encoding = font_get_encoding();
47 char *p1 = (char *)in;
48 char *p2 = out;
49 size_t ret;
50 iconv_t cd;
51
52 if ((cd = iconv_open("UTF-8", encoding)) == (iconv_t)-1)
53 G_fatal_error(_("Unable to convert from <%s> to UTF-8"), encoding);
54
55 ret = iconv(cd, &p1, &ilen, &p2, &olen);
56
58
59 *p2++ = '\0';
60
61 if (ret > 0)
62 G_warning(_("Some characters could not be converted to UTF-8"));
63 }
64#else
65 {
66 const unsigned char *p1 = (const unsigned char *)in;
67 unsigned char *p2 = (unsigned char *)out;
68 int i, j;
69
70 for (i = j = 0; i < ilen; i++) {
71 int c = p1[i];
72
73 if (c < 0x80)
74 p2[j++] = c;
75 else {
76 p2[j++] = 0xC0 + (c >> 6);
77 p2[j++] = 0x80 + (c & 0x3F);
78 }
79 }
80
81 p2[j++] = '\0';
82 }
83#endif
84
85 return out;
86}
87
88static void set_matrix(void)
89{
90 static cairo_matrix_t mat;
91
92 if (matrix_valid)
93 return;
94
98
100
101 matrix_valid = 1;
102}
103
104/*!
105 \brief Draw text
106
107 \param str string to be drawn
108 */
109void Cairo_Text(const char *str)
110{
111 char *utf8 = convert(str);
112
113 if (!utf8)
114 return;
115
116 set_matrix();
117
120
121 G_free(utf8);
122
123 ca.modified = 1;
124}
125
126/*
127 \brief Get text bounding box
128
129 \param str string
130 \param[out] t,b,l,r top, bottom, left, right corner
131 */
132void Cairo_text_box(const char *str, double *t, double *b, double *l, double *r)
133{
134 char *utf8 = convert(str);
136
137 if (!utf8)
138 return;
139
140 set_matrix();
141
143
144 G_free(utf8);
145
146 *l = cur_x + ext.x_bearing;
147 *r = cur_x + ext.x_bearing + ext.width;
148 *t = cur_y + ext.y_bearing;
149 *b = cur_y + ext.y_bearing + ext.height;
150}
151
152static void set_font_toy(const char *name)
153{
154 char *font = G_store(name);
157
158 for (;;) {
159 char *p = strrchr(font, '-');
160
161 if (!p)
162 break;
163
164 if (G_strcasecmp(p, "-bold") == 0)
166 else if (strcasecmp(p, "-italic") == 0)
168 else if (G_strcasecmp(p, "-oblique") == 0)
170 else
171 break;
172
173 *p = '\0';
174 }
175
177
178 G_free(font);
179}
180
181#if USE_FONTCONFIG
182
183static void fc_init(void)
184{
185 static int initialized;
186
187 if (!initialized) {
188 FcInit();
189 initialized = 1;
190 }
191}
192
193static void set_font_fc(const char *name)
194{
195 static cairo_font_face_t *face;
197 FcResult result;
198
199 fc_init();
200
201 if (face) {
203 face = NULL;
204 }
205
212}
213
214static void font_list_fc(char ***list, int *count, int verbose)
215{
219 char **fonts = *list;
220 int num_fonts = *count;
221 int i;
222
223 fc_init();
224
228
229 fonts = G_realloc(fonts, (num_fonts + fontset->nfont) * sizeof(char *));
230
231 for (i = 0; i < fontset->nfont; i++) {
232 char buf[1024];
233 FcPattern *pat = fontset->fonts[i];
234 FcChar8 *family = (FcChar8 *)"", *style = (FcChar8 *)"";
235
237 FcPatternGetString(pat, FC_STYLE, 0, &style);
238
239 if (verbose)
240 snprintf(buf, sizeof(buf), "%s:%s|%s:%s|%d|%s|%d|%s|", family,
241 style, family, style, GFONT_DRIVER, "", 0, "utf-8");
242 else
243 snprintf(buf, sizeof(buf), "%s:%s", family, style);
244
245 fonts[num_fonts++] = G_store(buf);
246 }
247
251
252 *list = fonts;
253 *count = num_fonts;
254}
255
256#endif
257
258static const char *toy_fonts[12] = {
259 "sans", "sans-italic", "sans-bold", "sans-bold-italic",
260 "serif", "serif-italic", "serif-bold", "serif-bold-italic",
261 "mono", "mono-italic", "mono-bold", "mono-bold-italic",
262};
263
264static const int num_toy_fonts = 12;
265
266static int is_toy_font(const char *name)
267{
268 int i;
269
270 for (i = 0; i < num_toy_fonts; i++)
271 if (G_strcasecmp(name, toy_fonts[i]) == 0)
272 return 1;
273
274 return 0;
275}
276
277/*!
278 \brief Set font
279
280 \param name font name
281 */
282void Cairo_set_font(const char *name)
283{
284#if USE_FONTCONFIG
285 if (is_toy_font(name))
286 set_font_toy(name);
287 else
289#else
290 set_font_toy(name);
291#endif
292}
293
294static void font_list_toy(char ***list, int *count, int verbose)
295{
296 char **fonts = *list;
297 int num_fonts = *count;
298 int i;
299
300 fonts = G_realloc(fonts, (num_fonts + num_toy_fonts) * sizeof(char *));
301
302 for (i = 0; i < num_toy_fonts; i++) {
303 char buf[256];
304
305 if (verbose)
306 snprintf(buf, sizeof(buf), "%s|%s|%d|%s|%d|%s|", toy_fonts[i],
307 toy_fonts[i], GFONT_DRIVER, "", 0, "utf-8");
308 else
309 strcpy(buf, toy_fonts[i]);
310 fonts[num_fonts++] = G_store(buf);
311 }
312
313 *list = fonts;
314 *count = num_fonts;
315}
316
317/*!
318 \brief Get list of fonts
319
320 \param[out] list font list
321 \param[out] count number of items in the list
322 */
323void Cairo_font_list(char ***list, int *count)
324{
325 font_list_toy(list, count, 0);
326#if USE_FONTCONFIG
328#endif
329}
330
331/*!
332 \brief Get fonts into
333
334 \param[out] list font list
335 \param[out] count number of items in the list
336 */
337void Cairo_font_info(char ***list, int *count)
338{
339 font_list_toy(list, count, 1);
340#if USE_FONTCONFIG
342#endif
343}
void Cairo_text_box(const char *str, double *t, double *b, double *l, double *r)
void Cairo_font_info(char ***list, int *count)
Get fonts into.
void Cairo_font_list(char ***list, int *count)
Get list of fonts.
void Cairo_Text(const char *str)
Draw text.
void Cairo_set_font(const char *name)
Set font.
GRASS cairo display driver - header file.
struct cairo_state ca
cairo_t * cairo
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:45
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
double text_size_y
Definition driver/init.c:34
double text_rotation
Definition driver/init.c:35
int matrix_valid
Definition driver/init.c:38
double text_size_x
Definition driver/init.c:33
double cur_x
Definition driver/init.c:30
double cur_y
Definition driver/init.c:31
const char * font_get_encoding(void)
Definition font.c:34
#define GFONT_DRIVER
Definition fontcap.h:21
#define M_PI
Definition gis.h:154
#define _(str)
Definition glocale.h:10
int count
const char * name
Definition named_colr.c:6
#define strcpy
Definition parson.c:66
double b
Definition r_raster.c:37
double l
Definition r_raster.c:37
double t
Definition r_raster.c:37
double r
Definition r_raster.c:37
#define strcasecmp
Definition strings.h:8
Definition manage.h:4