#include "config.h"
+#ifndef _ISOC99_SOURCE
+# define _ISOC99_SOURCE
+#endif
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+#endif
+
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
#include "sn_network.h"
#define Y_SPACING 40
static double x_offset = OUTER_SPACING;
-static int next_vertex_number = 0;
+static _Bool embedded = 0;
+
+static void exit_usage (void) /* {{{ */
+{
+ printf ("Usage: sn-svg [options] [file]\n"
+ "\n"
+ "Valid options are:\n"
+ " -e Create output suitable for embedding into other XML files.\n"
+ "\n");
+ exit (EXIT_FAILURE);
+} /* }}} void exit_usage */
+
+static int read_options (int argc, char **argv) /* {{{ */
+{
+ int option;
+
+ while ((option = getopt (argc, argv, "eh?")) != -1)
+ {
+ switch (option)
+ {
+ case 'e':
+ embedded = 1;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ exit_usage ();
+ }
+ }
-static int tex_show_stage (sn_stage_t *s)
+ return (0);
+} /* }}} int read_options */
+
+static double determine_stage_width (sn_stage_t *s) /* {{{ */
{
int lines[s->comparators_num];
int right[s->comparators_num];
int lines_used = 0;
int i;
- printf (" <!-- stage %i -->\n", SN_STAGE_DEPTH (s));
+ if (SN_STAGE_COMP_NUM (s) == 0)
+ return (0.0);
for (i = 0; i < SN_STAGE_COMP_NUM (s); i++)
{
int j;
sn_comparator_t *c = SN_STAGE_COMP_GET (s, i);
- int min_num;
- int max_num;
+ for (j = 0; j < lines_used; j++)
+ if (SN_COMP_LEFT (c) > right[j])
+ break;
+
+ lines[i] = j;
+ right[j] = SN_COMP_RIGHT (c);
+ if (j >= lines_used)
+ lines_used = j + 1;
+ }
+ assert (lines_used >= 1);
- min_num = next_vertex_number;
- next_vertex_number++;
+ return (((double) (lines_used - 1)) * INNER_SPACING);
+} /* }}} double determine_stage_width */
- max_num = next_vertex_number;
- next_vertex_number++;
+static double determine_network_width (sn_network_t *n) /* {{{ */
+{
+ double width;
+ int i;
+
+ /* Spacing between stages and at the beginning and end of the network */
+ width = (SN_NETWORK_STAGE_NUM (n) + 1) * OUTER_SPACING;
+
+ /* Spacing required within a stage */
+ for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++)
+ width += determine_stage_width (SN_NETWORK_STAGE_GET (n, i));
+
+ return (width);
+} /* }}} double determine_network_width */
+
+static int sn_svg_show_stage (sn_stage_t *s) /* {{{ */
+{
+ int lines[s->comparators_num];
+ int right[s->comparators_num];
+ int lines_used = 0;
+ int i;
+
+ printf (" <!-- stage %i -->\n", SN_STAGE_DEPTH (s));
+
+ for (i = 0; i < SN_STAGE_COMP_NUM (s); i++)
+ {
+ lines[i] = -1;
+ right[i] = -1;
+ }
+
+ for (i = 0; i < SN_STAGE_COMP_NUM (s); i++)
+ {
+ int j;
+ sn_comparator_t *c = SN_STAGE_COMP_GET (s, i);
for (j = 0; j < lines_used; j++)
if (SN_COMP_LEFT (c) > right[j])
int y1 = Y_OFFSET + (SN_COMP_MIN (c) * Y_SPACING);
int y2 = Y_OFFSET + (SN_COMP_MAX (c) * Y_SPACING);
- printf (" <line x1=\"%g\" y1=\"%i\" x2=\"%g\" y2=\"%i\" "
+ printf (" <svg:line x1=\"%g\" y1=\"%i\" x2=\"%g\" y2=\"%i\" "
"stroke=\"black\" stroke-width=\"1\" />\n"
- " <circle cx=\"%g\" cy=\"%i\" r=\"%g\" fill=\"black\" />\n"
- " <circle cx=\"%g\" cy=\"%i\" r=\"%g\" fill=\"black\" />\n",
+ " <svg:circle cx=\"%g\" cy=\"%i\" r=\"%g\" fill=\"black\" />\n"
+ " <svg:circle cx=\"%g\" cy=\"%i\" r=\"%g\" fill=\"black\" />\n",
x1, y1, x2, y2,
x1, y1, RADIUS,
x2, y2, RADIUS);
printf ("\n");
return (0);
-} /* int tex_show_stage */
+} /* }}} int sn_svg_show_stage */
-int main (int argc, char **argv)
+int main (int argc, char **argv) /* {{{ */
{
sn_network_t *n;
FILE *fh = NULL;
+
+ double svg_height;
+ double svg_width;
+
int i;
- if (argc == 1)
+ read_options (argc, argv);
+
+ if ((argc - optind) == 0)
fh = stdin;
- else if (argc == 2)
- fh = fopen (argv[1], "r");
+ else if ((argc - optind) == 1)
+ fh = fopen (argv[optind], "r");
if (fh == NULL)
- {
- printf ("fh == NULL!\n");
- return (1);
- }
+ exit_usage ();
n = sn_network_read (fh);
return (1);
}
- printf ("<?xml version=\"1.0\" standalone=\"no\"?>\n"
- "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
- "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
- "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n");
+ svg_height = (2 * Y_OFFSET) + ((SN_NETWORK_INPUT_NUM (n) - 1) * Y_SPACING);
+ svg_width = determine_network_width (n);
+
+ if (embedded)
+ printf ("<svg:svg version=\"1.1\" viewBox=\"0 0 %g %g\">\n",
+ svg_width, svg_height);
+ else
+ printf ("<?xml version=\"1.0\" standalone=\"no\"?>\n"
+ "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
+ "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
+ "<svg:svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" "
+ "width=\"%g\" height=\"%g\" viewBox=\"0 0 %g %g\">\n",
+ svg_width, svg_height, svg_width, svg_height);
printf ("<!-- Output generated with sn-svg from %s -->\n", PACKAGE_STRING);
for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++)
- tex_show_stage (SN_NETWORK_STAGE_GET (n, i));
+ sn_svg_show_stage (SN_NETWORK_STAGE_GET (n, i));
printf (" <!-- horizontal lines -->\n");
for (i = 0; i < SN_NETWORK_INPUT_NUM (n); i++)
- printf (" <line x1=\"%g\" y1=\"%i\" x2=\"%g\" y2=\"%i\" "
+ printf (" <svg:line x1=\"%g\" y1=\"%i\" x2=\"%g\" y2=\"%i\" "
"stroke=\"black\" stroke-width=\"1\" />\n",
0.0, Y_OFFSET + (i * Y_SPACING),
x_offset, Y_OFFSET + (i * Y_SPACING));
- printf ("</svg>\n");
+ printf ("</svg:svg>\n");
return (0);
-} /* int main */
+} /* }}} int main */
-/* vim: set shiftwidth=2 softtabstop=2 : */
+/* vim: set shiftwidth=2 softtabstop=2 fdm=marker : */