*/
static int svg_indent = 0;
static int svg_single_line = 0;
-static const char *svg_default_font = "Helvetica";
+static const char *svg_default_font = "-dummy-";
typedef struct svg_dash
{
int dash_enable;
static void svg_text(FILE *fp, gfx_node_t *node)
{
pdf_coords g;
+ const char *fontname;
/* as svg has 0,0 in top-left corner (like most screens) instead of
bottom-left corner like pdf and eps, we have to fake the coords
using offset and inverse sin(r) value */
svg_write_number(fp, page_height - g.tmy);
fputs("\"", fp);
}
-
-/* if (strcmp(node->filename, svg_default_font))
- fprintf(fp, " font-family=\"%s\"", node->filename);
- */
- fputs(" font-family=\"Helvetica", fp);
- fputs("\" font-size=\"", fp);
+ fontname = afm_get_font_name(node->filename);
+ if (strcmp(fontname, svg_default_font))
+ fprintf(fp, " font-family=\"%s\"", fontname);
+ fputs(" font-size=\"", fp);
svg_write_number(fp, node->size);
fputs("\"", fp);
if (!svg_color_is_black(node->color))
art_u32 width, art_u32 height,
gfx_color_t background, FILE *fp){
gfx_node_t *node = canvas->firstnode;
+ /* Find the first font used, and assume it is the mostly used
+ one. It reduces the number of font-familty attributes. */
+ while (node) {
+ if (node->type == GFX_TEXT && node->filename) {
+ svg_default_font = afm_get_font_name(node->filename);
+ break;
+ }
+ node = node->next;
+ }
fputs(
"<?xml version=\"1.0\" standalone=\"no\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n"
" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
"<!--\n"
-" SVG file created by RRDtool,\n"
-" Tobias Oetiker <tobi@oetike.ch>, http://tobi.oetiker.ch\n"
+" SVG file created by\n"
+" RRDtool 1.2.4 Tobias Oetiker, http://tobi.oetiker.ch\n"
"\n"
" The width/height attributes in the outhermost svg node\n"
" are just default sizes for the browser which is used\n"
fprintf(fp, " x=\"0\" y=\"0\" width=\"%d\" height=\"%d\"", width, height);
svg_write_color(fp, background, "fill");
svg_close_tag_empty_node(fp);
+ node = canvas->firstnode;
while (node) {
switch (node->type) {
case GFX_LINE:
int last_obj_id;
/*--*/
pdf_buffer pdf_header;
- pdf_buffer catalog_obj, pages_obj, page1_obj;
+ pdf_buffer info_obj, catalog_obj, pages_obj, page1_obj;
pdf_buffer fontsdict_obj;
pdf_buffer graph_stream;
} pdf_state;
pdf_puts(buf, tmp);
}
+static void pdf_put_string_contents(pdf_buffer *buf, const char *text)
+{
+ const char *p = text;
+ while (1) {
+ char ch = *p;
+ switch (ch) {
+ case 0: return;
+ case '(':
+ case ')':
+ case '\\':
+ case '\n':
+ case '\r':
+ case '\t':
+ pdf_puts(buf, "\\");
+ pdf_put(buf, (char)ch, 1);
+ break;
+ default:
+ if (ch >= 126 || ch < 32) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "\\%03o", ch);
+ pdf_puts(buf, tmp);
+ } else {
+ pdf_put(buf, p, 1);
+ }
+ }
+ p++;
+ }
+}
+
static void pdf_init_object(pdf_state *state, pdf_buffer *buf)
{
pdf_init_buffer(state, buf);
{
pdf_coords g;
pdf_buffer *s = &state->graph_stream;
- const unsigned char *p;
pdf_font *font = pdf_find_font(state, node);
if (font == NULL) {
rrd_set_error("font disappeared");
pdf_write_matrix(state, node, &g, 1);
pdf_puts(s, " Tm\n");
pdf_puts(s, "(");
- for (p = (const unsigned char*)node->text; *p; p++) {
- char tmp[30];
- switch (*p) {
- case '(':
- case ')':
- case '\\':
- case '\n':
- case '\r':
- case '\t':
- pdf_puts(s, "\\");
- /* fall-through */
- default:
- if (*p >= 126) {
- snprintf(tmp, sizeof(tmp), "\\%03o", *p);
- pdf_puts(s, tmp);
- } else {
- pdf_put(s, (const char*)p, 1);
- }
- }
- }
+ pdf_put_string_contents(s, node->text);
pdf_puts(s, ") Tj\n");
if (PDF_CALC_DEBUG || !next_is_text)
pdf_puts(s, "ET\n");
{
pdf_init_buffer(state, &state->pdf_header);
pdf_init_dict(state, &state->catalog_obj);
+ pdf_init_dict(state, &state->info_obj);
pdf_init_dict(state, &state->pages_obj);
pdf_init_dict(state, &state->page1_obj);
pdf_init_dict(state, &state->fontsdict_obj);
static void pdf_setup_document(pdf_state *state)
{
+ const char *creator = "RRDtool 1.2.4 Tobias Oetiker, http://tobi.oetiker.ch";
/* all objects created by now, so init code can reference them */
/* HEADER */
pdf_puts(&state->pdf_header, "%PDF-1.3\n");
/* following 8 bit comment is recommended by Adobe for
indicating binary file to file transfer applications */
pdf_puts(&state->pdf_header, "%\xE2\xE3\xCF\xD3\n");
+ /* INFO */
+ pdf_putsi(&state->info_obj, "/Creator (");
+ pdf_put_string_contents(&state->info_obj, creator);
+ pdf_puts(&state->info_obj, ")\n");
/* CATALOG */
pdf_putsi(&state->catalog_obj, "/Type /Catalog\n");
pdf_putsi(&state->catalog_obj, "/Pages ");
fprintf(state->fp, "<<\n");
fprintf(state->fp, "\t/Size %d\n", state->last_obj_id + 1);
fprintf(state->fp, "\t/Root %d 0 R\n", state->catalog_obj.id);
+ fprintf(state->fp, "\t/Info %d 0 R\n", state->info_obj.id);
fprintf(state->fp, ">>\n");
fprintf(state->fp, "startxref\n");
fprintf(state->fp, "%d\n", xref_pos);