[rrd-developers] [patch] [SVG] Support for CSS font families.

Alexander V Alekseev alex at alemate.ru
Fri May 25 16:25:59 CEST 2007


 		Hello!

 	As specified in SVG 1.1 specification
(http://www.w3.org/TR/SVG11/text.html#FontFamilyProperty), the only
fonts you can rely upon are 5 CSS2 font families:

'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'

(As specified at http://www.w3.org/TR/REC-CSS2/fonts.html#value-def-generic-family ).

 	But RRD 1.2.15 considers all of them unknown. I've made a small
patch (attached), which allows usage of those fonts for SVG output
format. (Font metrics are taken from RRD_AFM_DEFAULT_FONT).

 	This patch doesn't solve the general problem, that all font
calculation should depend on output format. But this is just my first patch
to rrd. ;-))

 	Bye. Alex.

-------------- next part --------------
--- rrdtool-1.2.15/src/rrd_gfx.c.orig	Mon May 21 20:29:39 2007
+++ rrdtool-1.2.15/src/rrd_gfx.c	Tue May 22 18:12:18 2007
@@ -282,7 +282,24 @@
   switch (canvas->imgformat) {
   case IF_PNG: 
     return gfx_get_text_width_libart (canvas, start, font, size, tabwidth, text, rotation);
-  case IF_SVG: /* fall through */ 
+  case IF_SVG:
+   /* There are 5 predefined fonts in SVG:
+    * 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'. 
+    * http://www.w3.org/TR/SVG11/text.html#FontFamilyProperty
+    * http://www.w3.org/TR/REC-CSS2/fonts.html#value-def-generic-family
+    *
+    * If any of them found, calculate metrics based on default font.
+    */
+   
+   if( strcasecmp(font,"serif") ||
+       strcasecmp(font,"sans-serif") ||
+       strcasecmp(font,"cursive") ||
+       strcasecmp(font,"fantasy") ||
+       strcasecmp(font,"monospace")
+     ){
+    	font=RRD_AFM_DEFAULT_FONT;
+   }
+   /* fall through */ 
   case IF_EPS:
   case IF_PDF:
     return afm_get_text_width(start, font, size, tabwidth, text);
@@ -916,9 +933,10 @@
 }
 
 
-static void pdf_calc(int page_height, gfx_node_t *node, pdf_coords *g)
+static void pdf_calc(int page_height, gfx_node_t *node, pdf_coords *g, enum gfx_if_en format)
 {
 	pdf_point a, b, c;
+	char *font;
 #if PDF_CALC_DEBUG
 	/* g->debug = !!strstr(node->text, "RevProxy-1") || !!strstr(node->text, "08:00"); */
 	g->debug = !!strstr(node->text, "sekunder") || !!strstr(node->text, "Web");
@@ -934,9 +952,32 @@
 		g->cos_r = 1;
 		g->sin_r = 0;
 	}
-	g->ascender = afm_get_ascender(node->filename, node->size);
-	g->descender = afm_get_descender(node->filename, node->size);
-	g->sizep.x = afm_get_text_width(0, node->filename, node->size, node->tabwidth, node->text);
+	if( format == IF_SVG ){
+		/* There are 5 predefined fonts in SVG:
+		 * 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'. 
+		 * http://www.w3.org/TR/SVG11/text.html#FontFamilyProperty
+		 * http://www.w3.org/TR/REC-CSS2/fonts.html#value-def-generic-family
+		 *
+		 * Substitute default font in theese cases.
+		 *
+		 */
+
+		if( strcasecmp(node->filename,"serif") &&
+				strcasecmp(node->filename,"sans-serif") &&
+				strcasecmp(node->filename,"cursive") &&
+				strcasecmp(node->filename,"fantasy") &&
+				strcasecmp(node->filename,"monospace")
+		  ){
+			font = node->filename;
+		} else {
+			font = RRD_AFM_DEFAULT_FONT;
+		}
+	}else{
+		font = node->filename;
+	}
+	g->ascender = afm_get_ascender(font, node->size);
+	g->descender = afm_get_descender(font, node->size);
+	g->sizep.x = afm_get_text_width(0, font, node->size, node->tabwidth, node->text);
 	/* seems like libart ignores the descender when doing vertial-align = bottom,
 	   so we do that too, to get labels v-aligning properly */
 	g->sizep.y = -g->ascender; /* + afm_get_descender(font->ps_font, node->size); */
@@ -1382,7 +1423,7 @@
 	  bottom-left corner like pdf and eps, we have to fake the coords
 	  using offset and inverse sin(r) value */
    int page_height = 1000;
-   pdf_calc(page_height, node, &g);
+   pdf_calc(page_height, node, &g,IF_SVG);
    if (node->angle != 0) {
      svg_start_tag(fp, "g");
 	 /* can't use svg_write_number as 2 decimals is far from enough to avoid
@@ -1399,7 +1440,22 @@
      svg_write_number(fp, page_height - g.tmy);
      fputs("\"", fp);
    }
-   fontname = afm_get_font_name(node->filename);
+   /* There are 5 predefined fonts in SVG:
+    * 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'. 
+    * http://www.w3.org/TR/SVG11/text.html#FontFamilyProperty
+    * http://www.w3.org/TR/REC-CSS2/fonts.html#value-def-generic-family
+    */
+   
+   if( strcasecmp(node->filename,"serif") &&
+       strcasecmp(node->filename,"sans-serif") &&
+       strcasecmp(node->filename,"cursive") &&
+       strcasecmp(node->filename,"fantasy") &&
+       strcasecmp(node->filename,"monospace")
+     ){
+	   fontname = afm_get_font_name(node->filename);
+   } else {
+	   fontname = node->filename;
+   }
    if (strcmp(fontname, svg_default_font))
      fprintf(fp, " font-family=\"%s\"", fontname);
    fputs(" font-size=\"", fp);
@@ -1423,7 +1479,22 @@
 	  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);
+		   /* There are 5 predefined fonts in SVG:
+		    * 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'. 
+		    * http://www.w3.org/TR/SVG11/text.html#FontFamilyProperty
+		    * http://www.w3.org/TR/REC-CSS2/fonts.html#value-def-generic-family
+		    */
+
+		   if( strcasecmp(node->filename,"serif") &&
+			   strcasecmp(node->filename,"sans-serif") &&
+			   strcasecmp(node->filename,"cursive") &&
+			   strcasecmp(node->filename,"fantasy") &&
+			   strcasecmp(node->filename,"monospace")
+		     ){
+			   svg_default_font = afm_get_font_name(node->filename);
+		   }else{
+			   svg_default_font = node->filename;
+		   }
 		   break;
 	   }
 	   node = node->next;
@@ -1754,7 +1825,7 @@
     if (!p)
 	return;
 #endif
-  pdf_calc(state->page_height, node, &g);
+  pdf_calc(state->page_height, node, &g,IF_EPS);
   eps_set_color(state, node->color);
   if (strcmp(ps_font, state->font) || node->size != state->font_size) {
     state->font = ps_font;
@@ -2287,7 +2358,7 @@
     state->has_failed = 1;
     return;
   }
-  pdf_calc(state->page_height, node, &g);
+  pdf_calc(state->page_height, node, &g,IF_PDF);
 #if PDF_CALC_DEBUG
   pdf_puts(s, "q % debug green box\n");
   pdf_write_matrix(state, node, &g, 0);


More information about the rrd-developers mailing list