rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const cairo_path_t *path)
{
    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
    RsvgState *state = rsvg_current_state (ctx);
    cairo_t *cr;
    int need_tmpbuf = 0;
    RsvgBbox bbox;
    double backup_tolerance;

    need_tmpbuf = ((state->fill != NULL) && (state->stroke != NULL) && state->opacity != 0xff)
        || state->clip_path_ref || state->mask || state->filter
        || (state->comp_op != CAIRO_OPERATOR_OVER);

    if (need_tmpbuf)
        rsvg_cairo_push_discrete_layer (ctx);

    cr = render->cr;

    cairo_set_antialias (cr, state->shape_rendering_type);

    _set_rsvg_affine (render, &state->affine);

    cairo_set_line_width (cr, _rsvg_css_normalize_length (&state->stroke_width, ctx, 'h'));
    cairo_set_miter_limit (cr, state->miter_limit);
    cairo_set_line_cap (cr, (cairo_line_cap_t) state->cap);
    cairo_set_line_join (cr, (cairo_line_join_t) state->join);
    cairo_set_dash (cr, state->dash.dash, state->dash.n_dash,
                    _rsvg_css_normalize_length (&state->dash.offset, ctx, 'o'));

    cairo_append_path (cr, path);

    rsvg_bbox_init (&bbox, &state->affine);

    backup_tolerance = cairo_get_tolerance (cr);
    cairo_set_tolerance (cr, 1.0);
    /* dropping the precision of cairo's bezier subdivision, yielding 2x
       _rendering_ time speedups, are these rather expensive operations
       really needed here? */

    /* Bounding box for fill
     *
     * Unlike the case for stroke, for fills we always compute the bounding box.
     * In GNOME we have SVGs for symbolic icons where each icon has a bounding
     * rectangle with no fill and no stroke, and inside it there are the actual
     * paths for the icon's shape.  We need to be able to compute the bounding
     * rectangle's extents, even when it has no fill nor stroke.
     */
    {
        RsvgBbox fb;
        rsvg_bbox_init (&fb, &state->affine);
        cairo_fill_extents (cr, &fb.rect.x, &fb.rect.y, &fb.rect.width, &fb.rect.height);
        fb.rect.width -= fb.rect.x;
        fb.rect.height -= fb.rect.y;
        fb.virgin = 0;
        rsvg_bbox_insert (&bbox, &fb);
    }

    /* Bounding box for stroke */
    if (state->stroke != NULL) {
        RsvgBbox sb;
        rsvg_bbox_init (&sb, &state->affine);
        cairo_stroke_extents (cr, &sb.rect.x, &sb.rect.y, &sb.rect.width, &sb.rect.height);
        sb.rect.width -= sb.rect.x;
        sb.rect.height -= sb.rect.y;
        sb.virgin = 0;
        rsvg_bbox_insert (&bbox, &sb);
    }

    cairo_set_tolerance (cr, backup_tolerance);

    rsvg_bbox_insert (&render->bbox, &bbox);

    if (state->fill != NULL) {
        int opacity;

        cairo_set_fill_rule (cr, state->fill_rule);

        if (!need_tmpbuf)
            opacity = (state->fill_opacity * state->opacity) / 255;
        else
            opacity = state->fill_opacity;

        _set_source_rsvg_paint_server (ctx,
                                       state->current_color,
                                       state->fill,
                                       opacity, bbox, rsvg_current_state (ctx)->current_color);

        if (state->stroke != NULL)
            cairo_fill_preserve (cr);
        else
            cairo_fill (cr);
    }

    if (state->stroke != NULL) {
        int opacity;
        if (!need_tmpbuf)
            opacity = (state->stroke_opacity * state->opacity) / 255;
        else
            opacity = state->stroke_opacity;

        _set_source_rsvg_paint_server (ctx,
                                       state->current_color,
                                       state->stroke,
                                       opacity, bbox, rsvg_current_state (ctx)->current_color);

        cairo_stroke (cr);
    }

    cairo_new_path (cr); /* clear the path in case stroke == fill == NULL; otherwise we leave it around from computing the bounding box */

    if (need_tmpbuf)
        rsvg_cairo_pop_discrete_layer (ctx);
}