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
25GVC_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
36GVC_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 */
53int 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 */
85int 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 */
117int 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 */
148int 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 */
182int 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 */
232void gvFreeRenderData (char* data)
233{
234 free (data);
235}
236
237void gvAddLibrary(GVC_t *gvc, gvplugin_library_t *lib)
238{
239 gvconfig_plugin_install_from_library(gvc, NULL, lib);
240}
241
242char **gvcInfo(GVC_t* gvc) { return gvc->common.info; }
243char *gvcVersion(GVC_t* gvc) { return gvc->common.info[1]; }
244char *gvcBuildDate(GVC_t* gvc) { return gvc->common.info[2]; }
245