#define EDGEALIGN 0
#endif
-// optimized gvputs for string literals
-#define GVPUTS(job, str) gvwrite((job), (str), sizeof(str) - 1)
-
typedef enum { FORMAT_SVG, FORMAT_SVGZ, } format_type;
/* SVG dash array */
for (i = 0; i < n; i++) {
gvwrite(job, &c, 1);
gvprintdouble(job, A[i].x);
- GVPUTS(job, ",");
+ gvputc(job, ',');
gvprintdouble(job, -A[i].y);
if (i == 0)
c = 'C'; /* second point */
for (i = n-1; i >= 0; i--) {
gvwrite(job, &c, 1);
gvprintdouble(job, A[i].x);
- GVPUTS(job, ",");
+ gvputc(job, ',');
gvprintdouble(job, -A[i].y);
if (i == 0)
c = 'C'; /* second point */
{
char* str;
- GVPUTS(job, "<g id=\"");
+ gvputs(job, "<g id=\"");
gvputs_xml(job, id);
if (idx) {
- GVPUTS(job, "_");
+ gvputc(job, '_');
gvputs_xml(job, idx);
}
gvprintf(job, "\" class=\"%s", kind);
if ((str = agget(obj, "class")) && *str) {
- GVPUTS(job, " ");
+ gvputc(job, ' ');
gvputs_xml(job, str);
}
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
static void svg_print_color(GVJ_t * job, gvcolor_t color)
break;
case RGBA_BYTE:
if (color.u.rgba[3] == 0) /* transparent */
- GVPUTS(job, "transparent");
+ gvputs(job, "transparent");
else
gvprintf(job, "#%02x%02x%02x",
color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
{
obj_state_t *obj = job->obj;
- GVPUTS(job, " fill=\"");
+ gvputs(job, " fill=\"");
if (filled == GRADIENT) {
gvprintf(job, "url(#l_%d)", gid);
} else if (filled == RGRADIENT) {
gvprintf(job, "\" fill-opacity=\"%f",
((float) obj->fillcolor.u.rgba[3] / 255.0));
} else {
- GVPUTS(job, "none");
+ gvputs(job, "none");
}
- GVPUTS(job, "\" stroke=\"");
+ gvputs(job, "\" stroke=\"");
svg_print_color(job, obj->pencolor);
if (obj->penwidth != PENWIDTH_NORMAL) {
- GVPUTS(job, "\" stroke-width=\"");
+ gvputs(job, "\" stroke-width=\"");
gvprintdouble(job, obj->penwidth);
}
if (obj->pen == PEN_DASHED) {
gvprintf(job, "\" stroke-opacity=\"%f",
((float) obj->pencolor.u.rgba[3] / 255.0));
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
static void svg_comment(GVJ_t * job, char *str)
{
- GVPUTS(job, "<!-- ");
+ gvputs(job, "<!-- ");
gvputs_xml(job, str);
- GVPUTS(job, " -->\n");
+ gvputs(job, " -->\n");
}
static void svg_begin_job(GVJ_t * job)
{
char *s;
- GVPUTS(job,
+ gvputs(job,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
if ((s = agget(job->gvc->g, "stylesheet")) && s[0]) {
- GVPUTS(job, "<?xml-stylesheet href=\"");
+ gvputs(job, "<?xml-stylesheet href=\"");
gvputs(job, s);
- GVPUTS(job, "\" type=\"text/css\"?>\n");
+ gvputs(job, "\" type=\"text/css\"?>\n");
}
- GVPUTS(job, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"
+ gvputs(job, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
"<!-- Generated by ");
gvputs_xml(job, job->common->info[0]);
- GVPUTS(job, " version ");
+ gvputs(job, " version ");
gvputs_xml(job, job->common->info[1]);
- GVPUTS(job, " (");
+ gvputs(job, " (");
gvputs_xml(job, job->common->info[2]);
- GVPUTS(job, ")\n"
+ gvputs(job, ")\n"
" -->\n");
}
{
obj_state_t *obj = job->obj;
- GVPUTS(job, "<!--");
+ gvputs(job, "<!--");
if (agnameof(obj->u.g)[0] && agnameof(obj->u.g)[0] != LOCALNAMEPREFIX) {
- GVPUTS(job, " Title: ");
+ gvputs(job, " Title: ");
gvputs_xml(job, agnameof(obj->u.g));
}
gvprintf(job, " Pages: %d -->\n",
job->canvasBox.UR.x,
job->canvasBox.UR.y);
/* namespace of svg */
- GVPUTS(job, " xmlns=\"http://www.w3.org/2000/svg\""
+ gvputs(job, " xmlns=\"http://www.w3.org/2000/svg\""
/* namespace of xlink */
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
">\n");
static void svg_end_graph(GVJ_t * job)
{
- GVPUTS(job, "</svg>\n");
+ gvputs(job, "</svg>\n");
}
static void svg_begin_layer(GVJ_t * job, char *layername, int layerNum,
obj_state_t *obj = job->obj;
svg_print_id_class(job, layername, NULL, "layer", obj->u.g);
- GVPUTS(job, ">\n");
+ gvputs(job, ">\n");
}
static void svg_end_layer(GVJ_t * job)
{
- GVPUTS(job, "</g>\n");
+ gvputs(job, "</g>\n");
}
/* svg_begin_page:
/* its really just a page of the graph, but its still a graph,
* and it is the entire graph if we're not currently paging */
svg_print_id_class(job, obj->id, NULL, "graph", obj->u.g);
- GVPUTS(job, " transform=\"scale(");
+ gvputs(job, " transform=\"scale(");
// cannot be gvprintdouble because 2 digits precision insufficient
gvprintf(job, "%g %g", job->scale.x, job->scale.y);
gvprintf(job, ") rotate(%d) translate(", -job->rotation);
gvprintdouble(job, job->translation.x);
- GVPUTS(job, " ");
+ gvputc(job, ' ');
gvprintdouble(job, -job->translation.y);
- GVPUTS(job, ")\">\n");
+ gvputs(job, ")\">\n");
/* default style */
if (agnameof(obj->u.g)[0] && agnameof(obj->u.g)[0] != LOCALNAMEPREFIX) {
- GVPUTS(job, "<title>");
+ gvputs(job, "<title>");
gvputs_xml(job, agnameof(obj->u.g));
- GVPUTS(job, "</title>\n");
+ gvputs(job, "</title>\n");
}
}
static void svg_end_page(GVJ_t * job)
{
- GVPUTS(job, "</g>\n");
+ gvputs(job, "</g>\n");
}
static void svg_begin_cluster(GVJ_t * job)
obj_state_t *obj = job->obj;
svg_print_id_class(job, obj->id, NULL, "cluster", obj->u.sg);
- GVPUTS(job, ">\n"
+ gvputs(job, ">\n"
"<title>");
gvputs_xml(job, agnameof(obj->u.g));
- GVPUTS(job, "</title>\n");
+ gvputs(job, "</title>\n");
}
static void svg_end_cluster(GVJ_t * job)
{
- GVPUTS(job, "</g>\n");
+ gvputs(job, "</g>\n");
}
static void svg_begin_node(GVJ_t * job)
else
idx = NULL;
svg_print_id_class(job, obj->id, idx, "node", obj->u.n);
- GVPUTS(job, ">\n"
+ gvputs(job, ">\n"
"<title>");
gvputs_xml(job, agnameof(obj->u.n));
- GVPUTS(job, "</title>\n");
+ gvputs(job, "</title>\n");
}
static void svg_end_node(GVJ_t * job)
{
- GVPUTS(job, "</g>\n");
+ gvputs(job, "</g>\n");
}
static void svg_begin_edge(GVJ_t * job)
char *ename;
svg_print_id_class(job, obj->id, NULL, "edge", obj->u.e);
- GVPUTS(job, ">\n"
+ gvputs(job, ">\n"
"<title>");
ename = strdup_and_subst_obj("\\E", obj->u.e);
gvputs_xml(job, ename);
free(ename);
- GVPUTS(job, "</title>\n");
+ gvputs(job, "</title>\n");
}
static void svg_end_edge(GVJ_t * job)
{
- GVPUTS(job, "</g>\n");
+ gvputs(job, "</g>\n");
}
static void
svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target,
char *id)
{
- GVPUTS(job, "<g");
+ gvputs(job, "<g");
if (id) {
- GVPUTS(job, " id=\"a_");
+ gvputs(job, " id=\"a_");
gvputs_xml(job, id);
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
- GVPUTS(job, ">"
+ gvputs(job, ">"
"<a");
if (href && href[0]) {
- GVPUTS(job, " xlink:href=\"");
+ gvputs(job, " xlink:href=\"");
const xml_flags_t flags = {0};
xml_escape(href, flags, (int(*)(void*, const char*))gvputs, job);
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
if (tooltip && tooltip[0]) {
- GVPUTS(job, " xlink:title=\"");
+ gvputs(job, " xlink:title=\"");
const xml_flags_t flags = {.raw = 1, .dash = 1, .nbsp = 1};
xml_escape(tooltip, flags, (int(*)(void*, const char*))gvputs, job);
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
if (target && target[0]) {
- GVPUTS(job, " target=\"");
+ gvputs(job, " target=\"");
gvputs_xml(job, target);
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
- GVPUTS(job, ">\n");
+ gvputs(job, ">\n");
}
static void svg_end_anchor(GVJ_t * job)
{
- GVPUTS(job, "</a>\n"
+ gvputs(job, "</a>\n"
"</g>\n");
}
char *family = NULL, *weight = NULL, *stretch = NULL, *style = NULL;
unsigned int flags;
- GVPUTS(job, "<text");
+ gvputs(job, "<text");
switch (span->just) {
case 'l':
- GVPUTS(job, " text-anchor=\"start\"");
+ gvputs(job, " text-anchor=\"start\"");
break;
case 'r':
- GVPUTS(job, " text-anchor=\"end\"");
+ gvputs(job, " text-anchor=\"end\"");
break;
default:
case 'n':
- GVPUTS(job, " text-anchor=\"middle\"");
+ gvputs(job, " text-anchor=\"middle\"");
break;
}
p.y += span->yoffset_centerline;
if (!obj->labeledgealigned) {
- GVPUTS(job, " x=\"");
+ gvputs(job, " x=\"");
gvprintdouble(job, p.x);
- GVPUTS(job, "\" y=\"");
+ gvputs(job, "\" y=\"");
gvprintdouble(job, -p.y);
- GVPUTS(job, "\"");
+ gvputs(job, "\"");
}
pA = span->font->postscript_alias;
if (pA) {
gvprintf(job, " font-family=\"%s", family);
if (pA->svg_font_family)
gvprintf(job, ",%s", pA->svg_font_family);
- GVPUTS(job, "\"");
+ gvputc(job, '"');
if (weight)
gvprintf(job, " font-weight=\"%s\"", weight);
if (stretch)
gvprintf(job, " font-family=\"%s\"", span->font->name);
if ((span->font) && (flags = span->font->flags)) {
if ((flags & HTML_BF) && !weight)
- GVPUTS(job, " font-weight=\"bold\"");
+ gvputs(job, " font-weight=\"bold\"");
if ((flags & HTML_IF) && !style)
- GVPUTS(job, " font-style=\"italic\"");
+ gvputs(job, " font-style=\"italic\"");
if ((flags & (HTML_UL|HTML_S|HTML_OL))) {
int comma = 0;
- GVPUTS(job, " text-decoration=\"");
+ gvputs(job, " text-decoration=\"");
if ((flags & HTML_UL)) {
- GVPUTS(job, "underline");
+ gvputs(job, "underline");
comma = 1;
}
if ((flags & HTML_OL)) {
}
if ((flags & HTML_S))
gvprintf(job, "%sline-through", (comma?",":""));
- GVPUTS(job, "\"");
+ gvputc(job, '"');
}
if ((flags & HTML_SUP))
- GVPUTS(job, " baseline-shift=\"super\"");
+ gvputs(job, " baseline-shift=\"super\"");
if ((flags & HTML_SUB))
- GVPUTS(job, " baseline-shift=\"sub\"");
+ gvputs(job, " baseline-shift=\"sub\"");
}
gvprintf(job, " font-size=\"%.2f\"", span->font->size);
default:
assert(0); /* internal error */
}
- GVPUTS(job, ">");
+ gvputc(job, '>');
if (obj->labeledgealigned) {
- GVPUTS(job, "<textPath xlink:href=\"#");
+ gvputs(job, "<textPath xlink:href=\"#");
gvputs_xml(job, obj->id);
- GVPUTS(job, "_p\" startOffset=\"50%\"><tspan x=\"0\" dy=\"");
+ gvputs(job, "_p\" startOffset=\"50%\"><tspan x=\"0\" dy=\"");
gvprintdouble(job, -p.y);
- GVPUTS(job, "\">");
+ gvputs(job, "\">");
}
const xml_flags_t xml_flags = {.raw = 1, .dash = 1, .nbsp = 1};
xml_escape(span->str, xml_flags, (int(*)(void*, const char*))gvputs, job);
if (obj->labeledgealigned)
- GVPUTS(job, "</tspan></textPath>");
- GVPUTS(job, "</text>\n");
+ gvputs(job, "</tspan></textPath>");
+ gvputs(job, "</text>\n");
}
/* svg_gradstyle
gvprintf(job,
"<defs>\n<linearGradient id=\"l_%d\" gradientUnits=\"userSpaceOnUse\" ", id);
- GVPUTS(job, "x1=\"");
+ gvputs(job, "x1=\"");
gvprintdouble(job, G[0].x);
- GVPUTS(job, "\" y1=\"");
+ gvputs(job, "\" y1=\"");
gvprintdouble(job, G[0].y);
- GVPUTS(job, "\" x2=\"");
+ gvputs(job, "\" x2=\"");
gvprintdouble(job, G[1].x);
- GVPUTS(job, "\" y2=\"");
+ gvputs(job, "\" y2=\"");
gvprintdouble(job, G[1].y);
- GVPUTS(job, "\" >\n");
+ gvputs(job, "\" >\n");
if (obj->gradient_frac > 0)
gvprintf(job, "<stop offset=\"%.03f\" style=\"stop-color:", obj->gradient_frac - 0.001);
else
- GVPUTS(job, "<stop offset=\"0\" style=\"stop-color:");
+ gvputs(job, "<stop offset=\"0\" style=\"stop-color:");
svg_print_color(job, obj->fillcolor);
- GVPUTS(job, ";stop-opacity:");
+ gvputs(job, ";stop-opacity:");
if (obj->fillcolor.type == RGBA_BYTE && obj->fillcolor.u.rgba[3] > 0
&& obj->fillcolor.u.rgba[3] < 255)
gvprintf(job, "%f", ((float) obj->fillcolor.u.rgba[3] / 255.0));
else
- GVPUTS(job, "1.");
- GVPUTS(job, ";\"/>\n");
+ gvputs(job, "1.");
+ gvputs(job, ";\"/>\n");
if (obj->gradient_frac > 0)
gvprintf(job, "<stop offset=\"%.03f\" style=\"stop-color:", obj->gradient_frac);
else
- GVPUTS(job, "<stop offset=\"1\" style=\"stop-color:");
+ gvputs(job, "<stop offset=\"1\" style=\"stop-color:");
svg_print_color(job, obj->stopcolor);
- GVPUTS(job, ";stop-opacity:");
+ gvputs(job, ";stop-opacity:");
if (obj->stopcolor.type == RGBA_BYTE && obj->stopcolor.u.rgba[3] > 0
&& obj->stopcolor.u.rgba[3] < 255)
gvprintf(job, "%f", ((float) obj->stopcolor.u.rgba[3] / 255.0));
else
- GVPUTS(job, "1.");
- GVPUTS(job, ";\"/>\n</linearGradient>\n</defs>\n");
+ gvputs(job, "1.");
+ gvputs(job, ";\"/>\n</linearGradient>\n</defs>\n");
return id;
}
"<defs>\n<radialGradient id=\"r_%d\" cx=\"50%%\" cy=\"50%%\" r=\"75%%\" "
"fx=\"%.0f%%\" fy=\"%.0f%%\">\n",
id, ifx, ify);
- GVPUTS(job, "<stop offset=\"0\" style=\"stop-color:");
+ gvputs(job, "<stop offset=\"0\" style=\"stop-color:");
svg_print_color(job, obj->fillcolor);
- GVPUTS(job, ";stop-opacity:");
+ gvputs(job, ";stop-opacity:");
if (obj->fillcolor.type == RGBA_BYTE && obj->fillcolor.u.rgba[3] > 0
&& obj->fillcolor.u.rgba[3] < 255)
gvprintf(job, "%f", ((float) obj->fillcolor.u.rgba[3] / 255.0));
else
- GVPUTS(job, "1.");
- GVPUTS(job, ";\"/>\n"
+ gvputs(job, "1.");
+ gvputs(job, ";\"/>\n"
"<stop offset=\"1\" style=\"stop-color:");
svg_print_color(job, obj->stopcolor);
- GVPUTS(job, ";stop-opacity:");
+ gvputs(job, ";stop-opacity:");
if (obj->stopcolor.type == RGBA_BYTE && obj->stopcolor.u.rgba[3] > 0
&& obj->stopcolor.u.rgba[3] < 255)
gvprintf(job, "%f", ((float) obj->stopcolor.u.rgba[3] / 255.0));
else
- GVPUTS(job, "1.");
- GVPUTS(job, ";\"/>\n</radialGradient>\n</defs>\n");
+ gvputs(job, "1.");
+ gvputs(job, ";\"/>\n</radialGradient>\n</defs>\n");
return id;
}
} else if (filled == (RGRADIENT)) {
gid = svg_rgradstyle(job);
}
- GVPUTS(job, "<ellipse");
+ gvputs(job, "<ellipse");
svg_grstyle(job, filled, gid);
- GVPUTS(job, " cx=\"");
+ gvputs(job, " cx=\"");
gvprintdouble(job, A[0].x);
- GVPUTS(job, "\" cy=\"");
+ gvputs(job, "\" cy=\"");
gvprintdouble(job, -A[0].y);
- GVPUTS(job, "\" rx=\"");
+ gvputs(job, "\" rx=\"");
gvprintdouble(job, A[1].x - A[0].x);
- GVPUTS(job, "\" ry=\"");
+ gvputs(job, "\" ry=\"");
gvprintdouble(job, A[1].y - A[0].y);
- GVPUTS(job, "\"/>\n");
+ gvputs(job, "\"/>\n");
}
static void
} else if (filled == (RGRADIENT)) {
gid = svg_rgradstyle(job);
}
- GVPUTS(job, "<path");
+ gvputs(job, "<path");
if (obj->labeledgealigned) {
- GVPUTS(job, " id=\"");
+ gvputs(job, " id=\"");
gvputs_xml(job, obj->id);
- GVPUTS(job, "_p\" ");
+ gvputs(job, "_p\" ");
}
svg_grstyle(job, filled, gid);
- GVPUTS(job, " d=\"");
+ gvputs(job, " d=\"");
svg_bzptarray(job, A, n);
- GVPUTS(job, "\"/>\n");
+ gvputs(job, "\"/>\n");
}
static void svg_polygon(GVJ_t * job, pointf * A, int n, int filled)
} else if (filled == (RGRADIENT)) {
gid = svg_rgradstyle(job);
}
- GVPUTS(job, "<polygon");
+ gvputs(job, "<polygon");
svg_grstyle(job, filled, gid);
- GVPUTS(job, " points=\"");
+ gvputs(job, " points=\"");
for (i = 0; i < n; i++) {
gvprintdouble(job, A[i].x);
- GVPUTS(job, ",");
+ gvputc(job, ',');
gvprintdouble(job, -A[i].y);
- GVPUTS(job, " ");
+ gvputc(job, ' ');
}
/* repeat the first point because Adobe SVG is broken */
gvprintdouble(job, A[0].x);
- GVPUTS(job, ",");
+ gvputc(job, ',');
gvprintdouble(job, -A[0].y);
- GVPUTS(job, "\"/>\n");
+ gvputs(job, "\"/>\n");
}
static void svg_polyline(GVJ_t * job, pointf * A, int n)
{
int i;
- GVPUTS(job, "<polyline");
+ gvputs(job, "<polyline");
svg_grstyle(job, 0, 0);
- GVPUTS(job, " points=\"");
+ gvputs(job, " points=\"");
for (i = 0; i < n; i++) {
gvprintdouble(job, A[i].x);
- GVPUTS(job, ",");
+ gvputc(job, ',');
gvprintdouble(job, -A[i].y);
- GVPUTS(job, " ");
+ gvputc(job, ' ');
}
- GVPUTS(job, "\"/>\n");
+ gvputs(job, "\"/>\n");
}
/* color names from http://www.w3.org/TR/SVG/types.html */