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