[cairo] SVG backend patch

Kristian Høgsberg krh at bitplanet.net
Mon Aug 1 19:50:04 PDT 2005

Emmanuel Pacaud wrote:
>>surface->fill_path() is working.  Next steps could be to get 
>>emit_solid_pattern() working.  Also, getting composite_trapezoids() 
>>working would make strokes work, so that's also worth looking into.  I'm 
>>thinking that the 'polygon' element would work well for trapezoids.
> You'll find attached the next iteration of my work in progress patch. It
> adds support for composite_trapezoids. As composite trapezoids will not
> produce acceptable SVG, I've also added an early fallback for stroke,
> and the corresponding function in SVG backend.

I agree, it should be possible to output strokes as svg stroked paths, 
but it's one of those things we've been discussing back and forth.  The 
short story is that stroking a path is hard and most ps/pdf/svg 
renderers expose some bugs and misrenderings when you go to extremes 
(very thick stroked paths doing sharp bends).  Cairo's algorithm for 
stroking paths is fairly simple and roboust, and by outputting the 
trapezoids, cairo output will look good even in renderers that have 
problems with these corner cases.

Now, outputting the trapezoids creates a huge and uneditable svg file, 
and is not what we want in any case.  Right now the stroking algorithm 
produces trapezoids directly, but the goal is to rewrite it to produce a 
new path that is the outline of the stroke and then fill that path. 
With this in place, the PDF, PS and SVG backends need not implement 
composite_trapezoids, since all drawing will go through fill_path.  Even 
so, I think that stroke_path is a backend function that we want and I 
think there should be a way for the user to specify wether strokes 
shoudl be output as strokes or fills.

>>Text is probably going to be a bit more tricky, since the svg text 
>>operators seem more highlevel than the show_glyphs() cairo backend 
> Will work on it after basic drawing is in place.
>>And I'm not sure what's the right thing to do for fonts - we 
>>could certainly generated an svg font subset to embed in the svg file, 
>>but I'm not sure how many svg viewers support that, and we loose hinting 
>>when we do that.
> I guess viewers should be smart enough to use a local font instead of
> embeded one.

We'll see how it works out.  My concern is that all other cairo backends 
  generate output that looks identical regardless of the environment. 
If we rely on the font being available on the system were the svg is 
viewed we're breaking from this rule.  But maybe that's acceptable for svg.

> What is also new in this version is the use of libxml. Please tell me if
> you feel this is wrong (or anything else in the patch).

I'm not convinced that we need libxml.  It's a big, somewhat political 
dependency, and we won't be using very much of it.  I think that 
instead, if you feel that the cairo_output_stream_t API is awkward, you 
should look into adding the convenience functions you need, for example

   cairo_output_stream_print_tag (stream, "path", "style", style, NULL);

even though that example doesn't seem too useful to me :-)  What I was 
thinking of was something like

   cairo_output_stream_printf (stream, "<path");
   emit_pattern (pattern, stream);
   cairo_output_stream_printf (stream, "/>\n");

and in emit_pattern:

   cairo_output_stream_printf (stream, " style=\"color: red;\");

A general comment: the cairo indent style is 4 spaces and further 
documented in the CODING_STYLE file.

> +cairo_int_status_t
> +_cairo_surface_stroke (cairo_operator_t		operator,
> +		       cairo_pattern_t		*pattern,
> +		       cairo_surface_t		*dst,
> +		       cairo_path_fixed_t	*path,
> +		       double			line_width,
> +		       cairo_line_cap_t		line_cap,
> +		       cairo_line_join_t	line_join,
> +		       double			miter_limit,
> +		       double			*dash,
> +		       int			num_dashes,
> +		       double			dash_offset,
> +		       cairo_matrix_t		*ctm_inverse)
> +{
> +	if (dst->backend->stroke)
> +		return dst->backend->stroke (operator, pattern, dst, path,
> +					     line_width, line_cap, line_join, miter_limit,
> +					     dash, num_dashes, dash_offset, ctm_inverse);
> +	else
> +}

The name of the function shold be stroke_path, i.e. 
_cairo_surface_stroke_path and backend->stroke_path to match up with 
fill_path.  Also, I've been thinking that instead of passing around all 
the line attributes (width, cap, join, miter limit, dashes) we could 
group them in a cairo_line_attributes_t struct in cairo_gstate_t and 
pass a pointer to that struct to _cairo_surface_stroke_path.


More information about the cairo mailing list