cairo-utils.cpp revision cf99b5253f47e8fa5ba3c655712fc15031d1d91a
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Helper functions to use cairo with inkscape
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright (C) 2007 bulia byak
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright (C) 2008 Johan Engelen
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Released under GNU GPL
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Key for cairo_surface_t to keep track of current color interpolation value
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Only the address of the structure is used, it is never initialized. See:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * http://www.cairographics.org/manual/cairo-Types.html#cairo-user-data-key-t
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisCairoGroup::CairoGroup(cairo_t *_ct) : ct(_ct), pushed(false) {}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisvoid CairoGroup::push_with_content(cairo_content_t content) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis cairo_push_group_with_content(ct, content);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis cairo_pattern_t *ret = cairo_pop_group(ct);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis throw std::logic_error("Cairo group popped without pushing it first");
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisCairo::RefPtr<Cairo::Pattern> CairoGroup::popmm() {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis cairo_pattern_t *ret = cairo_pop_group(ct);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis Cairo::RefPtr<Cairo::Pattern> retmm(new Cairo::Pattern(ret, true));
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis throw std::logic_error("Cairo group popped without pushing it first");
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisCairoContext::CairoContext(cairo_t *obj, bool ref)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisvoid CairoContext::transform(Geom::Affine const &m)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisvoid CairoContext::set_source_rgba32(guint32 color)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis cairo_set_source_rgba(cobj(), red, gre, blu, alp);
return ret;
feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & trans, Geom::Rect view, bool optimize_stroke)
if( is_straight_curve(c) )
if (!optimize_stroke) {
else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) {
if (!optimize_stroke) {
if (!optimize_stroke) {
cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) {
feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used
/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */
feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
if (!area)
if (!optimize_stroke) {
The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate
in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead,
/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift
feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
if (!area)
return SP_CSS_COLOR_INTERPOLATION_AUTO;
cairo_set_source_rgba(ct, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba));
return pbs;
int h = cairo_image_surface_get_height(s);
return ns;
return ns;
return ns;
return alpha;
return out;
static int ink_cairo_surface_average_color_internal(cairo_surface_t *surface, double &rf, double &gf, double &bf, double &af)
for (int x = 0; x < width; ++x) {
return px;
void ink_cairo_surface_average_color(cairo_surface_t *surface, double &r, double &g, double &b, double &a)
a /= count;
void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r, double &g, double &b, double &a)
r /= count;
g /= count;
b /= count;
a /= count;
void srgb_to_linear( double* c ) {
*c = unpremul_alpha( *c, a );
*c = (int)cc;
*c = premul_alpha( *c, a );
*c = unpremul_alpha( *c, a );
*c = (int)cc;
*c = premul_alpha( *c, a );
for (int x = 0; x < width; ++x) {
srgb_to_linear( &r, a );
srgb_to_linear( &g, a );
srgb_to_linear( &b, a );
for (int x = 0; x < width; ++x) {
linear_to_srgb( &r, a );
linear_to_srgb( &g, a );
linear_to_srgb( &b, a );
guint32 o = 0;
r = premul_alpha(r, a);
b = premul_alpha(b, a);
g = premul_alpha(g, a);
++px;
++px;
guint32 r, g, b, a;
return px;