[cairo] Can cairo generates <text> elements in the svg output ?

Jonathan Marchand jonathlela at gmail.com
Sun Feb 27 08:42:56 PST 2011


Hi,

I've produced a patch to make cairo use the <text> tag in the SVG
output. It still a very naive patch because I'm new to cairo and I am
not a C expert.
It covers all my needs, and I don't know any bugs. However, it should be
tested thoroughly. Is there a way or a procedure to assure the patch is
usable ?

Jonathan

On Fri, Nov 05, 2010 at 11:18:35AM +0100, Emmanuel Pacaud wrote:
> Hi,
> 
> Le vendredi 05 novembre 2010 à 11:03 +0100, Jonathan Marchand a écrit : 
> > Currently, cairo generates text in svg by means of path for each glyhs,
> > there is no <text> elements generated. Thus, there is no way to extract
> > the text from an output file.  This issue was addressed before[1], but
> > it seems that today cairo still lacks this feature.
> > 
> > Is this feature planned ? Are there strong fundamentals motives against
> > it ? Does it present technical difficulties to implement ?
> 
> To my knowledge, nobody is working on this feature. I've worked a bit on
> it a couple of years ago, but didn't produce anything usable.
> 
> There's no motive against it. It would be nice to have both output
> method available (<text> and <glyph>) though.
> 
> It should not be to difficult to implement, as the work for a text
> output was already done for the PDF backend.
> 
> Emmanuel.
> 
-------------- next part --------------
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index bb5bccf..4d02bc1 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2130,6 +2130,65 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t	   *output,
 }
 
 static cairo_int_status_t
+_cairo_svg_surface_emit_font_style (cairo_output_stream_t	*output,
+				    cairo_svg_surface_t		*surface,
+				    cairo_operator_t		op,
+				    const cairo_pattern_t	*source,
+				    const cairo_scaled_font_t	*scaled_font)
+{
+    double font_size;
+    const char *font_family;
+    const char *font_weight;
+    const char *font_slant;
+    cairo_status_t status;
+    
+    font_size = scaled_font->font_matrix.xx;
+    _cairo_output_stream_printf (output,
+				 "font-size:%f;", font_size);
+    
+    font_family = cairo_toy_font_face_get_family(scaled_font->original_font_face);
+    _cairo_output_stream_printf (output,
+				 "font-family:%s;", font_family);
+    
+    status = _cairo_svg_surface_emit_pattern (surface, source,
+					      output, FALSE, NULL);
+    if (unlikely (status))
+	return status;
+    _cairo_svg_surface_emit_operator_for_style (output, surface, op);
+    
+    switch (cairo_toy_font_face_get_weight(scaled_font->original_font_face))
+	{
+	case CAIRO_FONT_WEIGHT_BOLD:
+	    font_weight = "bold";
+	    break;
+	case CAIRO_FONT_WEIGHT_NORMAL:
+	default:
+	    font_weight = "normal";
+	    break;
+	};
+    _cairo_output_stream_printf (output,
+				 "font-weight:%s;", font_weight);
+    
+    switch (cairo_toy_font_face_get_slant(scaled_font->original_font_face))
+	{
+	case CAIRO_FONT_SLANT_ITALIC:
+	    font_slant = "italic";
+	    break;
+	case CAIRO_FONT_SLANT_OBLIQUE:
+	    font_slant = "oblique";
+	    break;
+	case CAIRO_FONT_SLANT_NORMAL:
+	default:
+	    font_slant = "normal";
+	    break;
+	}
+    _cairo_output_stream_printf (output,
+				 "font-style:%s;", font_slant);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
 _cairo_svg_surface_fill_stroke (void			*abstract_surface,
 				cairo_operator_t	 fill_op,
 				const cairo_pattern_t	*fill_source,
@@ -2560,6 +2619,81 @@ FALLBACK:
     return status;
 }
 
+static cairo_bool_t
+_cairo_svg_surface_has_show_text_glyphs	(void			*abstract_surface)
+{
+    return TRUE;
+}
+
+static cairo_int_status_t
+_cairo_svg_surface_show_text_glyphs (void			*abstract_surface,
+				     cairo_operator_t		 op,
+				     const cairo_pattern_t	*source,
+				     const char			*utf8,
+				     int			 utf8_len,
+				     cairo_glyph_t		*glyphs,
+				     int			 num_glyphs,
+				     const cairo_text_cluster_t *clusters,
+				     int			 num_clusters,
+				     cairo_text_cluster_flags_t	 cluster_flags,
+				     cairo_scaled_font_t	*scaled_font,
+				     cairo_clip_t		*clip)
+{
+    cairo_svg_surface_t *surface = abstract_surface;
+    cairo_output_stream_t *output = surface->xml_node;
+    cairo_status_t status;
+    int i;
+    cairo_matrix_t p2u;
+    double x, y;
+    
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return _cairo_svg_surface_analyze_operation (surface, op, source);
+    
+    assert (_cairo_svg_surface_operation_supported (surface, op, source));
+    
+    if (num_glyphs <= 0)
+	return CAIRO_STATUS_SUCCESS;
+    
+    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
+    if (unlikely (status))
+	return status;
+    
+    _cairo_output_stream_printf (output,
+				 "<text");
+    
+    p2u = source->matrix;
+    status = cairo_matrix_invert (&p2u);
+    assert (status == CAIRO_STATUS_SUCCESS);
+    _cairo_svg_surface_emit_transform (output, " transform", &p2u, NULL);
+    
+    _cairo_output_stream_printf (output,
+				 " style=\"");
+    
+    _cairo_svg_surface_emit_font_style(output, surface, op, source, scaled_font);
+    
+    _cairo_output_stream_printf (output,
+				 "\">\n");    
+    
+    x = glyphs[0].x;
+    y = glyphs[0].y;
+    cairo_matrix_transform_point (&source->matrix, &x, &y);
+    _cairo_output_stream_printf (output,
+				 "<tspan x=\"%f\" y=\"%f\">", x, y);
+    
+    for (i = 0; i < utf8_len; i++) {
+	_cairo_output_stream_printf (output,
+				     "%c", (utf8[i]));
+    }
+    
+    _cairo_output_stream_printf (output,
+				 "</tspan>\n");
+    
+    _cairo_output_stream_printf (output,
+				 "</text>\n");  
+    
+    return _cairo_output_stream_get_status (output);
+}
+
 static void
 _cairo_svg_surface_get_font_options (void                  *abstract_surface,
 				     cairo_font_options_t  *options)
@@ -2602,7 +2736,11 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
 	_cairo_svg_surface_show_glyphs,
 	NULL, /* snapshot */
 	NULL, /* is_similar */
-	_cairo_svg_surface_fill_stroke
+	_cairo_svg_surface_fill_stroke,
+	NULL, /* create_solid_pattern_surface */
+	NULL, /* can_repaint_solid_pattern_surface */
+	_cairo_svg_surface_has_show_text_glyphs,
+	_cairo_svg_surface_show_text_glyphs,
 };
 
 static cairo_status_t
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.cairographics.org/archives/cairo/attachments/20110227/4bbb0d3e/attachment-0001.pgp>


More information about the cairo mailing list