GRASS 8 Programmer's Manual  8.5.0dev(2025)-34f31bd7be
font2.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <grass/gis.h>
10 #include <grass/glocale.h>
11 
12 struct glyph {
13  unsigned int offset : 20;
14  unsigned int count : 12;
15 };
16 
17 static struct glyph *glyphs;
18 static int glyphs_alloc;
19 
20 static unsigned char *xcoords, *ycoords;
21 static int coords_offset;
22 static int coords_alloc;
23 
24 static int fontmap[1024];
25 static int num_chars;
26 
27 static char current_font[16];
28 static int font_loaded;
29 
30 static struct glyph *glyph_slot(int idx)
31 {
32  if (glyphs_alloc <= idx) {
33  int new_alloc = idx + ((glyphs_alloc > 0) ? 1000 : 4000);
34 
35  glyphs = G_realloc(glyphs, new_alloc * sizeof(struct glyph));
36  memset(&glyphs[glyphs_alloc], 0,
37  (new_alloc - glyphs_alloc) * sizeof(struct glyph));
38  glyphs_alloc = new_alloc;
39  }
40 
41  return &glyphs[idx];
42 }
43 
44 static int coord_slots(int count)
45 {
46  int n;
47 
48  if (coords_alloc < coords_offset + count) {
49  coords_alloc =
50  coords_offset + count + ((coords_alloc > 0) ? 10000 : 60000);
51  xcoords = G_realloc(xcoords, coords_alloc);
52  ycoords = G_realloc(ycoords, coords_alloc);
53  }
54 
55  n = coords_offset;
56  coords_offset += count;
57 
58  return n;
59 }
60 
61 static void read_hersh(const char *filename)
62 {
63  FILE *fp = fopen(filename, "r");
64 
65  if (!fp)
66  return;
67 
68  while (!feof(fp)) {
69  char buf[8];
70  struct glyph *glyph;
71  int coords;
72  unsigned int i, idx, count;
73  int c;
74 
75  switch (c = fgetc(fp)) {
76  case '\r':
77  fgetc(fp);
78  continue;
79  case '\n':
80  continue;
81  default:
82  ungetc(c, fp);
83  break;
84  }
85 
86  if (fread(buf, 1, 5, fp) != 5)
87  break;
88 
89  buf[5] = 0;
90  idx = atoi(buf);
91 
92  if (fread(buf, 1, 3, fp) != 3)
93  break;
94 
95  buf[3] = 0;
96  count = atoi(buf);
97 
98  glyph = glyph_slot(idx);
99  coords = coord_slots(count);
100 
101  glyph->offset = coords;
102  glyph->count = count;
103 
104  for (i = 0; i < count; i++) {
105  if ((i + 4) % 36 == 0) {
106  /* skip newlines? */
107  if (fgetc(fp) == '\r')
108  fgetc(fp);
109  }
110 
111  xcoords[coords + i] = fgetc(fp);
112  ycoords[coords + i] = fgetc(fp);
113  }
114 
115  if (fgetc(fp) == '\r')
116  fgetc(fp);
117  }
118 
119  fclose(fp);
120 }
121 
122 static void load_glyphs(void)
123 {
124  int i;
125 
126  if (glyphs)
127  return;
128 
129  for (i = 1; i <= 4; i++) {
130  char buf[GPATH_MAX];
131 
132  snprintf(buf, sizeof(buf), "%s/fonts/hersh.oc%d", G_gisbase(), i);
133  read_hersh(buf);
134  }
135 }
136 
137 static void read_fontmap(const char *name)
138 {
139  char buf[GPATH_MAX];
140  FILE *fp;
141 
142  num_chars = 0;
143  memset(fontmap, 0, sizeof(fontmap));
144 
145  snprintf(buf, sizeof(buf), "%s/fonts/%s.hmp", G_gisbase(), name);
146 
147  fp = fopen(buf, "r");
148  if (!fp) {
149  G_warning("Unable to open font map '%s': %s. "
150  "Try running 'g.mkfontcap --overwrite'",
151  buf, strerror(errno));
152  return;
153  }
154 
155  while (fscanf(fp, "%s", buf) == 1) {
156  int a, b;
157 
158  if (sscanf(buf, "%d-%d", &a, &b) == 2)
159  while (a <= b)
160  fontmap[num_chars++] = a++;
161  else if (sscanf(buf, "%d", &a) == 1)
162  fontmap[num_chars++] = a;
163  }
164 
165  fclose(fp);
166 }
167 
168 static void load_font(void)
169 {
170  if (font_loaded)
171  return;
172 
173  if (!glyphs)
174  load_glyphs();
175 
176  read_fontmap(current_font);
177 
178  font_loaded = 1;
179 }
180 
181 int font_init(const char *name)
182 {
183  if (strcmp(name, current_font) == 0)
184  return 0;
185 
186  if (G_strlcpy(current_font, name, sizeof(current_font)) >=
187  sizeof(current_font)) {
188  G_fatal_error(_("Font name <%s> is too long"), name);
189  }
190  font_loaded = 0;
191 
192  return 0;
193 }
194 
195 int get_char_vects(unsigned char achar, int *n, unsigned char **X,
196  unsigned char **Y)
197 {
198  struct glyph *glyph;
199  int i;
200 
201  if (!font_loaded)
202  load_font();
203 
204  i = (int)achar - 040; /* translate achar to char# in font index */
205  if (i <= 0 || i >= num_chars) {
206  *n = 0;
207  return 1;
208  }
209 
210  glyph = &glyphs[fontmap[i]];
211 
212  *n = glyph->count;
213  *X = &xcoords[glyph->offset];
214  *Y = &ycoords[glyph->offset];
215 
216  return 0;
217 }
#define G_realloc(p, n)
Definition: defs/gis.h:96
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:39
size_t G_strlcpy(char *, const char *, size_t)
Safe string copy function.
Definition: strlcpy.c:52
Header file for msvc/fcntl.c.
int get_char_vects(unsigned char achar, int *n, unsigned char **X, unsigned char **Y)
Definition: font2.c:195
int font_init(const char *name)
Definition: font2.c:181
#define GPATH_MAX
Definition: gis.h:199
#define _(str)
Definition: glocale.h:10
int count
const char * name
Definition: named_colr.c:6
#define X
Definition: ogsf.h:140
#define Y
Definition: ogsf.h:141
double b
Definition: r_raster.c:39