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 "gvc.h"
17 #include "const.h"
18 #include "gvcjob.h"
19 #include "gvcint.h"
20 #include "gvcproc.h"
21 #include "gvconfig.h"
22 #include "gvio.h"
23 #include <stdlib.h>
24
gvContext(void)25 GVC_t *gvContext(void)
26 {
27 GVC_t *gvc;
28
29 agattr(NULL, AGNODE, "label", NODENAME_ESC);
30 /* default to no builtins, demand loading enabled */
31 gvc = gvNEWcontext(NULL, TRUE);
32 gvconfig(gvc, FALSE); /* configure for available plugins */
33 return gvc;
34 }
35
gvContextPlugins(const lt_symlist_t * builtins,int demand_loading)36 GVC_t *gvContextPlugins(const lt_symlist_t *builtins, int demand_loading)
37 {
38 GVC_t *gvc;
39
40 agattr(NULL, AGNODE, "label", NODENAME_ESC);
41 gvc = gvNEWcontext(builtins, demand_loading);
42 gvconfig(gvc, FALSE); /* configure for available plugins */
43 return gvc;
44 }
45
46
47
48 /* gvLayout:
49 * Selects layout based on engine and binds it to gvc;
50 * does the layout and sets the graph's bbox.
51 * Return 0 on success.
52 */
gvLayout(GVC_t * gvc,graph_t * g,const char * engine)53 int gvLayout(GVC_t *gvc, graph_t *g, const char *engine)
54 {
55 char buf[256];
56 int rc;
57
58 rc = gvlayout_select(gvc, engine);
59 if (rc == NO_SUPPORT) {
60 agerr (AGERR, "Layout type: \"%s\" not recognized. Use one of:%s\n",
61 engine, gvplugin_list(gvc, API_layout, engine));
62 return -1;
63 }
64
65 if (gvLayoutJobs(gvc, g) == -1)
66 return -1;
67
68 /* set bb attribute for basic layout.
69 * doesn't yet include margins, scaling or page sizes because
70 * those depend on the renderer being used. */
71 if (GD_drawing(g)->landscape)
72 sprintf(buf, "%d %d %d %d",
73 ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x),
74 ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x));
75 else
76 sprintf(buf, "%d %d %d %d",
77 ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y),
78 ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y));
79 agsafeset(g, "bb", buf, "");
80
81 return 0;
82 }
83
84 /* Render layout in a specified format to an open FILE */
gvRender(GVC_t * gvc,graph_t * g,const char * format,FILE * out)85 int gvRender(GVC_t *gvc, graph_t *g, const char *format, FILE *out)
86 {
87 int rc;
88 GVJ_t *job;
89
90 g = g->root;
91
92 /* create a job for the required format */
93 rc = gvjobs_output_langname(gvc, format);
94 job = gvc->job;
95 if (rc == NO_SUPPORT) {
96 agerr (AGERR, "Format: \"%s\" not recognized. Use one of:%s\n",
97 format, gvplugin_list(gvc, API_device, format));
98 return -1;
99 }
100
101 job->output_lang = gvrender_select(job, job->output_langname);
102 if (!LAYOUT_DONE(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) {
103 agerrorf( "Layout was not done\n");
104 return -1;
105 }
106 job->output_file = out;
107 if (out == NULL)
108 job->flags |= OUTPUT_NOT_REQUIRED;
109 rc = gvRenderJobs(gvc, g);
110 gvrender_end_job(job);
111 gvjobs_delete(gvc);
112
113 return rc;
114 }
115
116 /* Render layout in a specified format to a file with the given name */
gvRenderFilename(GVC_t * gvc,graph_t * g,const char * format,const char * filename)117 int gvRenderFilename(GVC_t *gvc, graph_t *g, const char *format, const char *filename)
118 {
119 int rc;
120 GVJ_t *job;
121
122 g = g->root;
123
124 /* create a job for the required format */
125 rc = gvjobs_output_langname(gvc, format);
126 job = gvc->job;
127 if (rc == NO_SUPPORT) {
128 agerr(AGERR, "Format: \"%s\" not recognized. Use one of:%s\n",
129 format, gvplugin_list(gvc, API_device, format));
130 return -1;
131 }
132
133 job->output_lang = gvrender_select(job, job->output_langname);
134 if (!LAYOUT_DONE(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) {
135 agerrorf( "Layout was not done\n");
136 return -1;
137 }
138 gvjobs_output_filename(gvc, filename);
139 rc = gvRenderJobs(gvc, g);
140 gvrender_end_job(job);
141 gvdevice_finalize(job);
142 gvjobs_delete(gvc);
143
144 return rc;
145 }
146
147 /* Render layout in a specified format to an external context */
gvRenderContext(GVC_t * gvc,graph_t * g,const char * format,void * context)148 int gvRenderContext(GVC_t *gvc, graph_t *g, const char *format, void *context)
149 {
150 int rc;
151 GVJ_t *job;
152
153 g = g->root;
154
155 /* create a job for the required format */
156 rc = gvjobs_output_langname(gvc, format);
157 job = gvc->job;
158 if (rc == NO_SUPPORT) {
159 agerr(AGERR, "Format: \"%s\" not recognized. Use one of:%s\n",
160 format, gvplugin_list(gvc, API_device, format));
161 return -1;
162 }
163
164 job->output_lang = gvrender_select(job, job->output_langname);
165 if (!LAYOUT_DONE(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) {
166 agerrorf( "Layout was not done\n");
167 return -1;
168 }
169
170 job->context = context;
171 job->external_context = TRUE;
172
173 rc = gvRenderJobs(gvc, g);
174 gvrender_end_job(job);
175 gvdevice_finalize(job);
176 gvjobs_delete(gvc);
177
178 return rc;
179 }
180
181 /* Render layout in a specified format to a malloc'ed string */
gvRenderData(GVC_t * gvc,graph_t * g,const char * format,char ** result,unsigned int * length)182 int gvRenderData(GVC_t *gvc, graph_t *g, const char *format, char **result, unsigned int *length)
183 {
184 int rc;
185 GVJ_t *job;
186
187 g = g->root;
188
189 /* create a job for the required format */
190 rc = gvjobs_output_langname(gvc, format);
191 job = gvc->job;
192 if (rc == NO_SUPPORT) {
193 agerr(AGERR, "Format: \"%s\" not recognized. Use one of:%s\n",
194 format, gvplugin_list(gvc, API_device, format));
195 return -1;
196 }
197
198 job->output_lang = gvrender_select(job, job->output_langname);
199 if (!LAYOUT_DONE(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) {
200 agerrorf( "Layout was not done\n");
201 return -1;
202 }
203
204 /* page size on Linux, Mac OS X and Windows */
205 #define OUTPUT_DATA_INITIAL_ALLOCATION 4096
206
207 if(!result || !(*result = malloc(OUTPUT_DATA_INITIAL_ALLOCATION))) {
208 agerr(AGERR, "failure malloc'ing for result string");
209 return -1;
210 }
211
212 job->output_data = *result;
213 job->output_data_allocated = OUTPUT_DATA_INITIAL_ALLOCATION;
214 job->output_data_position = 0;
215
216 rc = gvRenderJobs(gvc, g);
217 gvrender_end_job(job);
218
219 if (rc == 0) {
220 *result = job->output_data;
221 *length = job->output_data_position;
222 }
223 gvjobs_delete(gvc);
224
225 return rc;
226 }
227
228 /* gvFreeRenderData:
229 * Utility routine to free memory allocated in gvRenderData, as the application code may use
230 * a different runtime library.
231 */
gvFreeRenderData(char * data)232 void gvFreeRenderData (char* data)
233 {
234 free (data);
235 }
236
gvAddLibrary(GVC_t * gvc,gvplugin_library_t * lib)237 void gvAddLibrary(GVC_t *gvc, gvplugin_library_t *lib)
238 {
239 gvconfig_plugin_install_from_library(gvc, NULL, lib);
240 }
241
gvcInfo(GVC_t * gvc)242 char **gvcInfo(GVC_t* gvc) { return gvc->common.info; }
gvcVersion(GVC_t * gvc)243 char *gvcVersion(GVC_t* gvc) { return gvc->common.info[1]; }
gvcBuildDate(GVC_t * gvc)244 char *gvcBuildDate(GVC_t* gvc) { return gvc->common.info[2]; }
245