*/
#define ENABLE_LIGATURES 0
-static const afm_fontinfo *afm_last_used_font;
+static const afm_fontinfo *afm_last_used_font = NULL;
#define is_font(p, name) \
(!strcmp(p->postscript_name, name) || !strcmp(p->fullname, name))
return NULL;
}
+static const char *last_unknown_font = NULL;
+
static const afm_fontinfo *afm_findfont(const char *name)
{
const afm_fontinfo *p = afm_searchfont(name);
if (p)
return p;
- if (1 || DEBUG) fprintf(stderr, "Can't find font '%s'\n", name);
- p = afm_searchfont("Helvetica");
+ if (!last_unknown_font || strcmp(name, last_unknown_font)) {
+ fprintf(stderr, "Can't find font '%s'\n", name);
+ last_unknown_font = name;
+ }
+ p = afm_searchfont("Courier");
if (p)
return p;
- return NULL;
+ return afm_fontinfolist; // anything, just anything.
}
const char *afm_get_font_postscript_name(const char* font)
{
const afm_fontinfo *p = afm_findfont(font);
- return p ? p->postscript_name : "Helvetica";
+ return p->postscript_name;
}
double afm_get_ascender(const char* font, double size)
{
const afm_fontinfo *p = afm_findfont(font);
- return p ? p->ascender : 10; /* just a guess to avoid really bad design if we don't know the font */
+ return size * p->ascender / 1000.0;
}
double afm_get_descender(const char* font, double size)
{
const afm_fontinfo *p = afm_findfont(font);
- return p ? p->descender : 4; /* just a guess to avoid really bad design if we don't know the font */
+ return size * p->descender / 1000.0;
}
static int afm_find_char_index(const afm_fontinfo *fontinfo,
"<!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"
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);