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 <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include "cdt.h"
18#include "render.h"
19
20static double timesFontWidth[] = {
21 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
22 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
23 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
24 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
25 0.2500, 0.3329, 0.4079, 0.5000, 0.5000, 0.8329, 0.7779, 0.3329, /* !"#$%&' */
26 0.3329, 0.3329, 0.5000, 0.5639, 0.2500, 0.3329, 0.2500, 0.2779, /* ()*+,-./ */
27 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, /* 01234567 */
28 0.5000, 0.5000, 0.2779, 0.2779, 0.5639, 0.5639, 0.5639, 0.4439, /* 89:;<=>? */
29 0.9209, 0.7219, 0.6669, 0.6669, 0.7219, 0.6109, 0.5559, 0.7219, /* @ABCDEFG */
30 0.7219, 0.3329, 0.3889, 0.7219, 0.6109, 0.8889, 0.7219, 0.7219, /* HIJKLMNO */
31 0.5559, 0.7219, 0.6669, 0.5559, 0.6109, 0.7219, 0.7219, 0.9439, /* PQRSTUVW */
32 0.7219, 0.7219, 0.6109, 0.3329, 0.2779, 0.3329, 0.4689, 0.5000, /* XYZ[\]^_ */
33 0.3329, 0.4439, 0.5000, 0.4439, 0.5000, 0.4439, 0.3329, 0.5000, /* `abcdefg */
34 0.5000, 0.2779, 0.2779, 0.5000, 0.2779, 0.7779, 0.5000, 0.5000, /* hijklmno */
35 0.5000, 0.5000, 0.3329, 0.3889, 0.2779, 0.5000, 0.5000, 0.7219, /* pqrstuvw */
36 0.5000, 0.5000, 0.4439, 0.4799, 0.1999, 0.4799, 0.5409, 0.2500, /* xyz{|}~ */
37 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
38 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
39 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
40 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
41 0.2500, 0.3329, 0.5000, 0.5000, 0.1669, 0.5000, 0.5000, 0.5000, /* ¡¢£¤¥¦§ */
42 0.5000, 0.1799, 0.4439, 0.5000, 0.3329, 0.3329, 0.5559, 0.5559, /* ¨©ª«¬­®¯ */
43 0.2500, 0.5000, 0.5000, 0.5000, 0.2500, 0.2500, 0.4529, 0.3499, /* ±²³´ ¶· */
44 0.3329, 0.4439, 0.4439, 0.5000, 1.0000, 1.0000, 0.2500, 0.4439, /* ¸¹º»¼½ ¿ */
45 0.2500, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, /* ÁÂÃÄÅÆÇ */
46 0.3329, 0.2500, 0.3329, 0.3329, 0.2500, 0.3329, 0.3329, 0.3329, /* È ÊË ÍÎÏ */
47 1.0000, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* Ð */
48 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */
49 0.2500, 0.8889, 0.2500, 0.2759, 0.2500, 0.2500, 0.2500, 0.2500, /* á ã */
50 0.6109, 0.7219, 0.8889, 0.3099, 0.2500, 0.2500, 0.2500, 0.2500, /* èéêë */
51 0.2500, 0.6669, 0.2500, 0.2500, 0.2500, 0.2779, 0.2500, 0.2500, /* ñ õ */
52 0.2779, 0.5000, 0.7219, 0.5000, 0.2500, 0.2500, 0.2500, 0.2500, /* øùúû */
53};
54static double arialFontWidth[] = {
55 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
56 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
57 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
58 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
59 0.2779, 0.2779, 0.3549, 0.5559, 0.5559, 0.8889, 0.6669, 0.2209, /* !"#$%&' */
60 0.3329, 0.3329, 0.3889, 0.5839, 0.2779, 0.3329, 0.2779, 0.2779, /* ()*+,-./ */
61 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, /* 01234567 */
62 0.5559, 0.5559, 0.2779, 0.2779, 0.5839, 0.5839, 0.5839, 0.5559, /* 89:;<=>? */
63 1.0149, 0.6669, 0.6669, 0.7219, 0.7219, 0.6669, 0.6109, 0.7779, /* @ABCDEFG */
64 0.7219, 0.2779, 0.5000, 0.6669, 0.5559, 0.8329, 0.7219, 0.7779, /* HIJKLMNO */
65 0.6669, 0.7779, 0.7219, 0.6669, 0.6109, 0.7219, 0.6669, 0.9439, /* PQRSTUVW */
66 0.6669, 0.6669, 0.6109, 0.2779, 0.2779, 0.2779, 0.4689, 0.5559, /* XYZ[\]^_ */
67 0.2219, 0.5559, 0.5559, 0.5000, 0.5559, 0.5559, 0.2779, 0.5559, /* `abcdefg */
68 0.5559, 0.2219, 0.2219, 0.5000, 0.2219, 0.8329, 0.5559, 0.5559, /* hijklmno */
69 0.5559, 0.5559, 0.3329, 0.5000, 0.2779, 0.5559, 0.5000, 0.7219, /* pqrstuvw */
70 0.5000, 0.5000, 0.5000, 0.3339, 0.2599, 0.3339, 0.5839, 0.2779, /* xyz{|}~ */
71 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
72 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
73 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
74 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
75 0.2779, 0.3329, 0.5559, 0.5559, 0.1669, 0.5559, 0.5559, 0.5559, /* ¡¢£¤¥¦§ */
76 0.5559, 0.1909, 0.3329, 0.5559, 0.3329, 0.3329, 0.5000, 0.5000, /* ¨©ª«¬­®¯ */
77 0.2779, 0.5559, 0.5559, 0.5559, 0.2779, 0.2779, 0.5369, 0.3499, /* ±²³´ ¶· */
78 0.2219, 0.3329, 0.3329, 0.5559, 1.0000, 1.0000, 0.2779, 0.6109, /* ¸¹º»¼½ ¿ */
79 0.2779, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, /* ÁÂÃÄÅÆÇ */
80 0.3329, 0.2779, 0.3329, 0.3329, 0.2779, 0.3329, 0.3329, 0.3329, /* È ÊË ÍÎÏ */
81 1.0000, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* Ð */
82 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */
83 0.2779, 1.0000, 0.2779, 0.3699, 0.2779, 0.2779, 0.2779, 0.2779, /* á ã */
84 0.5559, 0.7779, 1.0000, 0.3649, 0.2779, 0.2779, 0.2779, 0.2779, /* èéêë */
85 0.2779, 0.8889, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* ñ õ */
86 0.2219, 0.6109, 0.9439, 0.6109, 0.2779, 0.2779, 0.2779, 0.2779, /* øùúû */
87};
88static double courFontWidth[] = {
89 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
90 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
91 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
92 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
93 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* !"#$%&' */
94 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ()*+,-./ */
95 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* 01234567 */
96 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* 89:;<=>? */
97 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* @ABCDEFG */
98 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* HIJKLMNO */
99 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* PQRSTUVW */
100 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* XYZ[\]^_ */
101 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* `abcdefg */
102 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* hijklmno */
103 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* pqrstuvw */
104 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* xyz{|}~ */
105 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
106 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
107 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
108 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
109 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¡¢£¤¥¦§ */
110 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¨©ª«¬­®¯ */
111 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ±²³´ ¶· */
112 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¸¹º»¼½ ¿ */
113 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ÁÂÃÄÅÆÇ */
114 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* È ÊË ÍÎÏ */
115 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* Ð */
116 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */
117 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* á ã */
118 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* èéêë */
119 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ñ õ */
120 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* øùúû */
121};
122
123/* estimate_textspan_size:
124 * Estimate size of textspan, for given face and size, in points.
125 */
126static void
127estimate_textspan_size(textspan_t * span, char **fontpath)
128{
129 double *Fontwidth, fontsize;
130 char c, *p, *fpp, *fontname;
131
132 fontname = span->font->name;
133 fontsize = span->font->size;
134
135 span->size.x = 0.0;
136 span->size.y = fontsize * LINESPACING;
137 span->yoffset_layout = 0.0;
138 span->yoffset_centerline = 0.1 * fontsize;
139 span->layout = NULL;
140 span->free_layout = NULL;
141
142 if (!strncasecmp(fontname, "cour", 4)) {
143 fpp = "[internal courier]";
144 Fontwidth = courFontWidth;
145 } else if (!strncasecmp(fontname, "arial", 5)
146 || !strncasecmp(fontname, "helvetica", 9)) {
147 fpp = "[internal arial]";
148 Fontwidth = arialFontWidth;
149 } else {
150 fpp = "[internal times]";
151 Fontwidth = timesFontWidth;
152 }
153 if (fontpath)
154 *fontpath = fpp;
155 if ((p = span->str)) {
156 while ((c = *p++))
157 span->size.x += Fontwidth[(unsigned char) c];
158 /* NOTE: Tables are based on a font of size 1. Need to multiply by
159 * fontsize to get appropriate value.
160 */
161 span->size.x *= fontsize;
162 }
163}
164
165/*
166 * This table maps standard Postscript font names to URW Type 1 fonts.
167 *
168 * The original source is in ps_font_equiv.txt. This is sorted
169 * during make into ps_font_equiv.h to ensure that it is in the right
170 * order for bsearch()
171 */
172static PostscriptAlias postscript_alias[] = {
173#include "ps_font_equiv.h"
174};
175
176static int fontcmpf(const void *a, const void *b)
177{
178 return (strcasecmp(((PostscriptAlias*)a)->name, ((PostscriptAlias*)b)->name));
179}
180
181static PostscriptAlias* translate_postscript_fontname(char* fontname)
182{
183 static PostscriptAlias key;
184 static PostscriptAlias *result;
185
186 if (key.name == NULL || strcasecmp(key.name, fontname)) {
187 free(key.name);
188 key.name = strdup(fontname);
189 result = (PostscriptAlias *) bsearch((void *) &key,
190 (void *) postscript_alias,
191 sizeof(postscript_alias) / sizeof(PostscriptAlias),
192 sizeof(PostscriptAlias),
193 fontcmpf);
194 }
195 return result;
196}
197
198pointf textspan_size(GVC_t *gvc, textspan_t * span)
199{
200 char **fpp = NULL, *fontpath = NULL;
201 textfont_t *font;
202
203 assert(span->font);
204 font = span->font;
205
206 assert(font->name);
207
208 /* only need to find alias once per font, since they are unique in dict */
209 if (! font->postscript_alias)
210 font->postscript_alias = translate_postscript_fontname(font->name);
211
212 if (Verbose && emit_once(font->name))
213 fpp = &fontpath;
214
215 if (! gvtextlayout(gvc, span, fpp))
216 estimate_textspan_size(span, fpp);
217
218 if (fpp) {
219 if (fontpath)
220 fprintf(stderr, "fontname: \"%s\" resolved to: %s\n",
221 font->name, fontpath);
222 else
223 fprintf(stderr, "fontname: unable to resolve \"%s\"\n", font->name);
224 }
225
226 return span->size;
227}
228
229static void* textfont_makef(Dt_t* dt, void* obj, Dtdisc_t* disc)
230{
231 textfont_t *f1 = (textfont_t*)obj;
232 textfont_t *f2 = calloc(1,sizeof(textfont_t));
233
234 /* key */
235 if (f1->name) f2->name = strdup(f1->name);
236 if (f1->color) f2->color = strdup(f1->color);
237 f2->flags = f1->flags;
238 f2->size = f1->size;
239
240 /* non key */
241 f2->postscript_alias = f1->postscript_alias;
242
243 return f2;
244}
245
246static void textfont_freef(Dt_t* dt, void* obj, Dtdisc_t* disc)
247{
248 textfont_t *f = (textfont_t*)obj;
249
250 if (f->name) free(f->name);
251 if (f->color) free(f->color);
252 free(f);
253}
254
255static int textfont_comparf (Dt_t* dt, void* key1, void* key2, Dtdisc_t* disc)
256{
257 int rc;
258 textfont_t *f1 = (textfont_t*)key1, *f2 = (textfont_t*)key2;
259
260 if (f1->name || f2->name) {
261 if (! f1->name) return -1;
262 if (! f2->name) return 1;
263 rc = strcmp(f1->name, f2->name);
264 if (rc) return rc;
265 }
266 if (f1->color || f2->color) {
267 if (! f1->color) return -1;
268 if (! f2->color) return 1;
269 rc = strcmp(f1->color, f2->color);
270 if (rc) return rc;
271 }
272 rc = (f1->flags - f2->flags);
273 if (rc) return rc;
274 if (f1->size < f2->size) return -1;
275 if (f1->size > f2->size) return 1;
276 return 0;
277}
278
279Dt_t * textfont_dict_open(GVC_t *gvc)
280{
281 DTDISC(&(gvc->textfont_disc),0,sizeof(textfont_t),-1,textfont_makef,textfont_freef,textfont_comparf,NULL,NULL,NULL);
282 gvc->textfont_dt = dtopen(&(gvc->textfont_disc), Dtoset);
283 return gvc->textfont_dt;
284}
285
286void textfont_dict_close(GVC_t *gvc)
287{
288 dtclose(gvc->textfont_dt);
289}
290