Graphviz  2.41.20171026.1811
gvtextlayout_gd.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include "config.h"
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "gvplugin_textlayout.h"
20 #include "gd.h"
21 
22 #ifdef HAVE_GD_FREETYPE
23 
24 /* fontsize at which text is omitted entirely */
25 #define FONTSIZE_MUCH_TOO_SMALL 0.15
26 /* fontsize at which text is rendered by a simple line */
27 #define FONTSIZE_TOO_SMALL 1.5
28 
29 #ifndef HAVE_GD_FONTCONFIG
30 /* gd_alternate_fontlist;
31  * Sometimes fonts are stored under a different name,
32  * especially on Windows. Without fontconfig, we provide
33  * here some rudimentary name mapping.
34  */
35 char *gd_alternate_fontlist(char *font)
36 {
37  static char *fontbuf;
38  static int fontbufsz;
39  char *p, *fontlist;
40  int len;
41 
42  len = strlen(font) + 1;
43  if (len > fontbufsz) {
44  fontbufsz = 2 * len;
45  if (fontbuf == NULL)
46  fontbuf = malloc(fontbufsz);
47  else
48  fontbuf = realloc(fontbuf, fontbufsz);
49  }
50 
51  /* fontbuf to contain font without style descriptions like -Roman or -Italic */
52  strcpy(fontbuf, font);
53  if ((p = strchr(fontbuf, '-')) || (p = strchr(fontbuf, '_')))
54  *p = 0;
55 
56  fontlist = fontbuf;
57  if ((strcasecmp(font, "times-bold") == 0)
58  || (strcasecmp(fontbuf, "timesbd") == 0)
59  || (strcasecmp(fontbuf, "timesb") == 0))
60  fontlist = "timesbd;Timesbd;TIMESBD;timesb;Timesb;TIMESB";
61 
62  else if ((strcasecmp(font, "times-italic") == 0)
63  || (strcasecmp(fontbuf, "timesi") == 0))
64  fontlist = "timesi;Timesi;TIMESI";
65 
66  else if ((strcasecmp(font, "timesnewroman") == 0)
67  || (strcasecmp(font, "timesnew") == 0)
68  || (strcasecmp(font, "timesroman") == 0)
69  || (strcasecmp(fontbuf, "times") == 0))
70  fontlist = "times;Times;TIMES";
71 
72  else if ((strcasecmp(font, "arial-bold") == 0)
73  || (strcasecmp(fontbuf, "arialb") == 0))
74  fontlist = "arialb;Arialb;ARIALB";
75 
76  else if ((strcasecmp(font, "arial-italic") == 0)
77  || (strcasecmp(fontbuf, "ariali") == 0))
78  fontlist = "ariali;Ariali;ARIALI";
79 
80  else if (strcasecmp(fontbuf, "helvetica") == 0)
81  fontlist = "helvetica;Helvetica;HELVETICA;arial;Arial;ARIAL";
82 
83  else if (strcasecmp(fontbuf, "arial") == 0)
84  fontlist = "arial;Arial;ARIAL";
85 
86  else if (strcasecmp(fontbuf, "courier") == 0)
87  fontlist = "courier;Courier;COURIER;cour";
88 
89  return fontlist;
90 }
91 #endif /* HAVE_GD_FONTCONFIG */
92 
93 /* gd_psfontResolve:
94  * * Construct alias for postscript fontname.
95  * * NB. Uses a static array - non-reentrant.
96  * */
97 
98 #define ADD_ATTR(a) \
99  if (a) { \
100  strcat(buf, comma ? " " : ", "); \
101  comma = 1; \
102  strcat(buf, a); \
103  }
104 
106 {
107  static char buf[1024];
108  int comma=0;
109  strcpy(buf, pa->family);
110 
111  ADD_ATTR(pa->weight);
112  ADD_ATTR(pa->stretch);
113  ADD_ATTR(pa->style);
114 
115  return buf;
116 }
117 
118 static boolean gd_textlayout(textspan_t * span, char **fontpath)
119 {
120  char *err, *fontlist, *fontname;
121  double fontsize;
122  int brect[8];
123  gdFTStringExtra strex;
124 #ifdef HAVE_GD_FONTCONFIG
125  PostscriptAlias *pA;
126 #endif
127 
128  fontname = span->font->name;
129  fontsize = span->font->size;
130 
131  strex.fontpath = NULL;
132  strex.flags = gdFTEX_RETURNFONTPATHNAME | gdFTEX_RESOLUTION;
133  strex.hdpi = strex.vdpi = POINTS_PER_INCH;
134 
135  if (strstr(fontname, "/"))
136  strex.flags |= gdFTEX_FONTPATHNAME;
137  else
138  strex.flags |= gdFTEX_FONTCONFIG;
139 
140  span->size.x = 0.0;
141  span->size.y = 0.0;
142  span->yoffset_layout = 0.0;
143 
144  span->layout = NULL;
145  span->free_layout = NULL;
146 
147  span->yoffset_centerline = 0.1 * fontsize;
148 
149  if (fontname) {
150  if (fontsize <= FONTSIZE_MUCH_TOO_SMALL) {
151  return TRUE; /* OK, but ignore text entirely */
152  } else if (fontsize <= FONTSIZE_TOO_SMALL) {
153  /* draw line in place of text */
154  /* fake a finite fontsize so that line length is calculated */
155  fontsize = FONTSIZE_TOO_SMALL;
156  }
157  /* call gdImageStringFT with null *im to get brect and to set font cache */
158 #ifdef HAVE_GD_FONTCONFIG
159  gdFTUseFontConfig(1); /* tell gd that we really want to use fontconfig, 'cos it s not the default */
160  pA = span->font->postscript_alias;
161  if (pA)
162  fontlist = gd_psfontResolve (pA);
163  else
164  fontlist = fontname;
165 #else
166  fontlist = gd_alternate_fontlist(fontname);
167 #endif
168 
169  err = gdImageStringFTEx(NULL, brect, -1, fontlist,
170  fontsize, 0, 0, 0, span->str, &strex);
171 
172  if (err) {
173  agerr(AGERR,"%s\n", err);
174  return FALSE; /* indicate error */
175  }
176 
177  if (fontpath)
178  *fontpath = strex.fontpath;
179  else
180  free (strex.fontpath); /* strup'ed in libgd */
181 
182  if (span->str && span->str[0]) {
183  /* can't use brect on some archtectures if strlen 0 */
184  span->size.x = (double) (brect[4] - brect[0]);
185  /* 1.2 specifies how much extra space to leave between lines;
186  * see LINESPACING in const.h.
187  */
188  span->size.y = (int)(fontsize * 1.2);
189  }
190  }
191  return TRUE;
192 }
193 
194 static gvtextlayout_engine_t gd_textlayout_engine = {
195  gd_textlayout,
196 };
197 #endif
198 
200 #ifdef HAVE_GD_FREETYPE
201  {0, "textlayout", 2, &gd_textlayout_engine, NULL},
202 #endif
203  {0, NULL, 0, NULL, NULL}
204 };
pointf size
Definition: textspan.h:64
Definition: cgraph.h:388
gvplugin_installed_t gvtextlayout_gd_types[]
char * weight
Definition: textspan.h:35
double size
Definition: textspan.h:52
char * stretch
Definition: textspan.h:36
char * gd_psfontResolve(PostscriptAlias *pa)
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:141
char * name
Definition: textspan.h:49
#define POINTS_PER_INCH
Definition: geom.h:62
char * str
Definition: textspan.h:59
int
Definition: grammar.c:1264
#define FONTSIZE_TOO_SMALL
Definition: const.h:292
double y
Definition: geom.h:28
double yoffset_centerline
Definition: textspan.h:63
PostscriptAlias * postscript_alias
Definition: textspan.h:51
#define NULL
Definition: logic.h:39
double yoffset_layout
Definition: textspan.h:63
double x
Definition: geom.h:28
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:21
char * style
Definition: textspan.h:37
void(* free_layout)(void *layout)
Definition: textspan.h:62
#define FONTSIZE_MUCH_TOO_SMALL
Definition: const.h:290
char * family
Definition: textspan.h:34
#define FALSE
Definition: cgraph.h:35
textfont_t * font
Definition: textspan.h:60
void * layout
Definition: textspan.h:61
#define TRUE
Definition: cgraph.h:38