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 | |
20 | static 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 | }; |
54 | static 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 | }; |
88 | static 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 | */ |
126 | static void |
127 | estimate_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 | */ |
172 | static PostscriptAlias postscript_alias[] = { |
173 | #include "ps_font_equiv.h" |
174 | }; |
175 | |
176 | static int fontcmpf(const void *a, const void *b) |
177 | { |
178 | return (strcasecmp(((PostscriptAlias*)a)->name, ((PostscriptAlias*)b)->name)); |
179 | } |
180 | |
181 | static 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 | |
198 | pointf 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 | |
229 | static 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 | |
246 | static 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 | |
255 | static 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 | |
279 | Dt_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 | |
286 | void textfont_dict_close(GVC_t *gvc) |
287 | { |
288 | dtclose(gvc->textfont_dt); |
289 | } |
290 | |